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。
Sample Input
4 5 2
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
1 5
Sample Output
6
6
HINT
100%的数据满足2<N<100000,1<M<200000。所用道路长度大于0小于10000。
数据已加强By Vfleaking
正解:$spfa$最短路+堆。
这题正解太鬼畜了。。简直毫无道理可言啊。。
首先,我们可以$yy$一下,一个图去掉最短路的一条边以后的最短路可以分为$3$条路:$1$->最短路上的点$u$->一条非最短路->最短路上的点$v$->$n$。于是我们就可以一顿乱搞了。。
首先,我们预处理出$1-n$的最短路和$n-1$的最短路。然后,我们删除每条边时,我们把这条边的入点弄出来,并限制住这条边,跑一遍$spfa$,当我们松弛到当前点$u$在最短路上更靠后的点时,我们就把当前$1-n$的路算出来,把这条路丢到堆里去。最后我们把堆中包含当前堵塞的路弹掉,然后直接查询最小距离就行了。不过为什么这个做法复杂度是对的。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define N (100010) 16 #define il inline 17 #define RG register 18 #define ll long long 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 struct data{ 24 int id,dis; 25 bool operator < (const data &a) const{ 26 return dis>a.dis; 27 } 28 }; 29 30 struct edge{ int nt,to,dis; }g1[2*N],g2[2*N]; 31 32 struct E{ int u,v,w; }G[2*N]; 33 34 priority_queue <data> Q; 35 36 int head1[N],head2[N],vis[N],vi[N],dis[N],dis1[N],dis2[N]; 37 int lim[N],id[N],s[N],q[50*N],n,m,l,cnt,ecnt,num1,num2; 38 39 il int gi(){ 40 RG int x=0,q=1; RG char ch=getchar(); 41 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 42 if (ch==‘-‘) q=-1,ch=getchar(); 43 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 44 return q*x; 45 } 46 47 il void insert1(RG int from,RG int to,RG int dis){ 48 g1[++num1]=(edge){head1[from],to,dis},head1[from]=num1; return; 49 } 50 51 il void insert2(RG int from,RG int to,RG int dis){ 52 g2[++num2]=(edge){head2[from],to,dis},head2[from]=num2; return; 53 } 54 55 il void spfa(RG int S,RG int lim){ 56 RG int h=0,t=1; dis[S]=dis1[S],vis[S]=1,q[t]=S; 57 while (h<t){ 58 RG int x=q[++h],v; 59 for (RG int i=head1[x];i;i=g1[i].nt){ 60 if (i==lim) continue; v=g1[i].to; 61 if (id[v]>id[S]) Q.push((data){id[v],dis[x]+g1[i].dis+dis2[v]}); 62 else if (dis[v]>dis[x]+g1[i].dis){ 63 dis[v]=dis[x]+g1[i].dis; 64 if (!vis[v]) vis[v]=1,q[++t]=v; 65 } 66 } 67 vis[x]=0; 68 } 69 return; 70 } 71 72 il void work(){ 73 n=gi(),m=gi(),l=gi(); 74 for (RG int i=1,u,v,w;i<=m;++i){ 75 u=gi(),v=gi(),w=gi(),G[++ecnt]=(E){u,v,w}; 76 insert1(u,v,w),insert2(v,u,w); 77 } 78 for (RG int i=1,x;i<=l;++i){ 79 x=gi(),vi[G[x].u]=vi[G[x].v]=1; 80 s[i]=G[x].u,s[i+1]=G[x].v,lim[G[x].u]=x; 81 dis1[G[x].v]=dis1[G[x].u]+g1[x].dis; 82 dis2[G[x].u]=g1[x].dis,id[s[i]]=++cnt; 83 } 84 id[s[l+1]]=++cnt; 85 for (RG int i=l;i;--i) dis2[s[i]]+=dis2[s[i+1]]; 86 for (RG int i=1;i<=n;++i) dis[i]=inf; 87 for (RG int i=1;i<=l;++i){ 88 spfa(s[i],lim[s[i]]); 89 while (!Q.empty() && Q.top().id<=id[s[i]]) Q.pop(); 90 if (Q.empty()){ puts("-1"); continue; } 91 printf("%d\n",Q.top().dis); 92 } 93 return; 94 } 95 96 int main(){ 97 File("road"); 98 work(); 99 return 0; 100 }