[JZOJ5133][SDOI省隊集訓2017]重建
阿新 • • 發佈:2019-02-20
題目描述
傻逼題
預處理每個圖裡經過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);
}
}