1. 程式人生 > >[JZOJ5133][SDOI省隊集訓2017]重建

[JZOJ5133][SDOI省隊集訓2017]重建

題目描述

這裡寫圖片描述

傻逼題

預處理每個圖裡經過k條邊的最短路。
然後可以用單調棧求出一些關鍵的c值使得某副圖改變最短路經過的邊數。
接著順序掃這些關鍵點,解方程即可。

#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
typedef long double db;
const int
maxn=1000+10,maxm=10000+10; const db eps=1e-12; const ll inf=100000000000000; struct dong{ ll c; int ca,x; } a[maxn*2]; ll f[maxn][maxn],g[maxn][maxn],gg; int h[maxn],go[maxm*2],dis[maxm*2],next[maxm*2],sta[maxn]; ll xy[maxn],ans,p; db q; int h2[maxn],g2[maxm*2],d2[maxm*2],n2[maxm*2],b[maxn]; bool bz[maxn]; int i,j,k,l,r,s
,t,n,m,tot,top,cnt,num,ca,sa,sb; void add(int x,int y,int z){ go[++tot]=y; dis[tot]=z; next[tot]=h[x]; h[x]=tot; } void add2(int x,int y,int z){ g2[++top]=y; d2[top]=z; n2[top]=h2[x]; h2[x]=top; } bool cmp(dong a,dong b){ return a.c<b.c; } ll cil(db q){ db p=floor(q
); return ll(p+1); } ll getxy(int x,int y){ if (f[s][x]>f[s][y]) return 0; q=(db)(f[s][y]-f[s][x])/(x-y); return cil(q); } ll getyx(int x,int y){ if (g[s][x]>g[s][y]) return 0; q=(db)(g[s][y]-g[s][x])/(x-y); return cil(q); } int main(){ freopen("rebuild.in","r",stdin);freopen("rebuild.out","w",stdout); scanf("%d",&ca); while (ca--){ scanf("%d%d%d%d",&n,&m,&s,&t); tot=top=0; fo(i,1,n) h[i]=h2[i]=bz[i]=0; fo(i,1,m){ scanf("%d%d%d",&j,&k,&l); add(j,k,l);add(k,j,l); } scanf("%d",&num); fo(i,1,num){ scanf("%d",&j); b[i]=j; bz[j]=1; } fo(i,1,m){ j=go[i*2-1];k=go[i*2];l=dis[i*2]; if (bz[j]&&bz[k]){ add2(j,k,l); add2(k,j,l); } } fo(i,1,n) fo(j,0,n) f[i][j]=inf; f[t][0]=0; fo(j,1,n){ fo(i,1,n){ r=h[i]; while (r){ f[i][j]=min(f[i][j],f[go[r]][j-1]+dis[r]); r=next[r]; } } } fo(i,1,num) fo(j,0,num) g[b[i]][j]=inf; g[t][0]=0; fo(j,1,num){ fo(i,1,num){ r=h2[b[i]]; while (r){ g[b[i]][j]=min(g[b[i]][j],g[g2[r]][j-1]+d2[r]); r=n2[r]; } } } cnt=0; top=0; fd(i,n,0){ if (f[s][i]==inf) continue; while (top&&getxy(sta[top],i)<=xy[top]) top--; sta[++top]=i; if (top>1) xy[top]=getxy(sta[top-1],i); } sa=sta[1]; fo(i,1,top-1){ a[++cnt].c=xy[i+1]; a[cnt].ca=1; a[cnt].x=sta[i+1]; } top=0; fd(i,num,0){ if (g[s][i]==inf) continue; while (top&&getyx(sta[top],i)<=xy[top]) top--; sta[++top]=i; if (top>1) xy[top]=getyx(sta[top-1],i); } if (!top){ printf("Impossible\n"); continue; } sb=sta[1]; fo(i,1,top-1){ a[++cnt].c=xy[i+1]; a[cnt].ca=2; a[cnt].x=sta[i+1]; } sort(a+1,a+cnt+1,cmp); ans=-1; fo(i,0,cnt){ if ((i<cnt&&a[i].c!=a[i+1].c)||i==cnt){ if (sa==sb){ if (f[s][sa]==g[s][sb]) ans=(i==cnt?-2:a[i+1].c-1); } else{ gg=f[s][sa]-g[s][sb]; r=sb-sa; if (gg%r==0){ p=(ll)gg/r; if (p<a[i+1].c&&a[i].c<=p) ans=p; } } } if (i<cnt){ if (a[i+1].ca==1) sa=a[i+1].x; else sb=a[i+1].x; } } if (ans==-1) printf("Impossible\n"); else if (ans==-2) printf("Infinity\n"); else printf("%lld\n",ans); } }