【题意概述】
修改图中任一一条边的边权,使其加倍,问怎样使修改后图中的1~n的最短路最大。输出最短路的增量。
【题解】
先跑一遍dijkstra求出1~n的路径长度,记录下经过的边。枚举这些边进行修改,再跑dijkstra求出某条边修改后的最短路径的长度。
1 #include2 #include 3 #include 4 #define LL long long 5 #define N 200010 6 #define rg register 7 using namespace std; 8 int n,m,tot,ans0,ans1,fa,son,cnt,last[N],pos[N],dis[N],fp[N],fe[N],st[N]; 9 struct edge{int to,pre,d;}e[N]; 10 struct heap{int poi,d;}h[N]; 11 inline int read(){ 12 int k=0,f=1; char c=getchar(); 13 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 14 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 15 return k*f; 16 } 17 inline void up(int x){ 18 while((fa=(x>>1))>0&&h[fa].d>h[x].d) 19 swap(h[fa],h[x]),swap(pos[h[fa].poi],pos[h[x].poi]),x=fa; 20 } 21 inline void down(int x){ 22 while((son=(x<<1))<=tot){ 23 if(h[son+1].d ; 24 if(h[son].d son; 25 else break; 26 } 27 } 28 inline void dijkstra(int x){ 29 for(rg int i=1;i<=n;i++) dis[i]=1e9,pos[i]=0; 30 h[tot=pos[x]=1]=(heap){x,dis[x]=0}; 31 while(tot){ 32 int now=h[1].poi; pos[h[tot].poi]=1; h[1]=h[tot--]; if(tot) down(1); 33 for(rg int i=last[now],to;i;i=e[i].pre)if(dis[to=e[i].to]>dis[now]+e[i].d){ 34 dis[to]=dis[now]+e[i].d; fp[to]=now; fe[to]=i; 35 if(!pos[to]) h[pos[to]=++tot]=(heap){to,dis[to]}; 36 else h[pos[to]].d=dis[to]; 37 up(pos[to]); 38 } 39 } 40 } 41 int main(){ 42 n=read(); m=read(); 43 for(rg int i=1;i<=m;i++){ 44 int u=read(),v=read(),d=read(); 45 e[++tot]=(edge){v,last[u],d}; last[u]=tot; 46 e[++tot]=(edge){u,last[v],d}; last[v]=tot; 47 } 48 dijkstra(1); 49 ans0=dis[n]; 50 int now=n; 51 while(fp[now]){ 52 st[++cnt]=fe[now]; 53 // printf("now=%d\n",now); 54 now=fp[now]; 55 } 56 // for(rg int i=1;i<=cnt;i++) printf("%d ",st[i]); 57 for(rg int i=1;i<=cnt;i++){ 58 int ed=st[i]; 59 if(ed&1) e[ed].d<<=1, e[ed+1].d<<=1; 60 else e[ed].d<<=1, e[ed-1].d<<=1; 61 dijkstra(1); 62 if(ed&1) e[ed].d>>=1, e[ed+1].d>>=1; 63 else e[ed].d>>=1, e[ed-1].d>>=1; 64 ans1=max(ans1,dis[n]); 65 // printf("dis=%d\n",dis[n]); 66 } 67 printf("%d\n",ans1-ans0); 68 return 0; 69 }