bzoj 3575: [Hnoi2014]道路堵塞
Description
A 国有N座城市,依次标为1到N。同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数。现在,A国交通部指定了一条从城市1到城市N的路径, 并且保证这条路径的长度是所有从城市1到城市N的路径中最短的。不幸的是,因为从城市1到城市N旅行的人越来越多,这条由交通部指定的路径经常发生堵塞。 现在A国想知道,这条路径中的任意一条道路无法通行时,由城市1到N的最短路径长度是多少。
Input
输入文件第一行是三个用空格分开的正整数N、M和L,分别表示城市数目、单向道路数目和交通部指定的最短路径包含多少条道路。
按下来M行,每行三个用空格分开的整数a、b和c,表示存在一条由城市a到城市b的长度为c的单向道路。这M行的行号也是对应道路的编号,即其中第1行对
应的道路编号为1,第2行对应的道路编号为2,…,第M行对应的道路编号为M。最后一行为L个用空格分开的整数sp(1)…,,sp(L),依次表示从城
市1到城市N的由交通部指定的最短路径上的道路的编号。
Output
输出文件包含L行,每行为一个整数,第i行(i=1,2…,,L)的整数表示删去编号为sp(i)的道路后从城市1到城市N的最短路径长度。如果去掉后没有从城市1到城市N的路径,则输出一1。
真的是连SPFA都不会...
根据玄学猜想:删掉最短路上的一条边后的最短路一定是由三段组成:
最短路上的一段 1--x,非最短路上的一段x--y,以及最短路上的一段y--n;
然后对于每次删掉一条连接(u,v)的边我们就把u放入队列中,并强制不走删掉的那一条边,拿u来松弛其它点到1的最短路
如果走到了最短路上的某个点x,并且该点在最短路上的标号比u大(在u后面),把这个点放入堆中即可
这个我们只需要维护好两个数组,一个1到每个最短路上的点的距离,一个是每个最短路上的点到n的距离
之后就可以愉快的跑SPFA了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | // MADE BY QT666 #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<queue> #include<cstring> using namespace std; typedef long long ll; const int N=700050; int gi() { int x=0,flag=1; char ch=getchar(); while (ch< '0' ||ch> '9' ){ if (ch== '-' ) flag=-1;ch=getchar();} while (ch>= '0' &&ch<= '9' ) x=x*10+ch- '0' ,ch=getchar(); return x*flag; } int head[N],to[N],nxt[N],c[N],cnt; int pre[N],pre2[N],id[N],to2[N],n,m,L; int a[N],vis[N],vis2[N],q[N*10],q2[N*10],dis[N]; struct data{ int id,dis; bool operator < ( const data &a) const { return a.dis<dis;} }b[N]; priority_queue<data>Q; void lnk( int x, int y, int z){ to[++cnt]=y,c[cnt]=z,nxt[cnt]=head[x],head[x]=cnt; } void spfa( int x, int y, int z){ dis[x]=pre[id[x]]; int t=0,sum=1,tail=0;q[0]=x;q2[++tail]=x; vis[x]=1; for ( int i=1;i<=L+1;i++) vis2[to2[i]]=0; while (t<sum){ int now=q[t++];vis[now]=0; for ( int i=head[now];i;i=nxt[i]){ if (i!=y){ int u=to[i]; if (id[u]>z){ if (!vis2[u]){ b[u].dis=dis[now]+c[i]+pre2[id[u]]; b[u].id=id[u];vis2[u]=1; q2[++tail]=u; } else b[u].dis=min(b[u].dis,dis[now]+c[i]+pre2[id[u]]); } else { if (dis[u]>dis[now]+c[i]){ dis[u]=dis[now]+c[i]; if (!vis[u]) vis[u]=1,q[sum++]=u; } } } } } while (tail) Q.push(b[q2[tail]]),tail--; } int main(){ n=gi(),m=gi(),L=gi(); for ( int i=1;i<=m;i++){ int x=gi(),y=gi(),z=gi(); lnk(x,y,z); } to2[1]=id[1]=1; for ( int i=1;i<=L;i++){ a[i]=gi(); to2[i+1]=to[a[i]]; id[to[a[i]]]=i+1; } for ( int i=1;i<=L;i++) pre[i+1]=pre[i]+c[a[i]]; for ( int i=L;i>=1;i--) pre2[i]=pre2[i+1]+c[a[i]]; memset(dis,127, sizeof (dis)); for ( int i=1;i<=L;i++){ spfa(to2[i],a[i],i); while (!Q.empty()&&Q.top().id<=i) Q.pop(); if (Q.empty()) puts( "-1" ); else printf( "%d\n" ,Q.top().dis); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步