bzoj1726:[Usaco2006 Nov]Roadblocks 次短路
Description
贝茜把家搬到了一个小农场,但她常常回到FJ的农场去拜访她的朋友。贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样,选择最短路。 贝茜所在的乡村有R(1<=R<=100,000)条双向道路,每条路都联结了所有的N(1<=N<=5000)个农场中的某两个。贝茜居住在农场1,她的朋友们居住在农场N(即贝茜每次旅行的目的地)。 贝茜选择的第二短的路径中,可以包含任何一条在最短路中出现的道路,并且,一条路可以重复走多次。当然咯,第二短路的长度必须严格大于最短路(可能有多条)的长度,但它的长度必须不大于所有除最短路外的路径的长度。
Input
* 第1行: 两个整数,N和R,用空格隔开
* 第2..R+1行: 每行包含三个用空格隔开的整数A、B和D,表示存在一条长度为 D(1 <= D <= 5000)的路连接农场A和农场B
* 第2..R+1行: 每行包含三个用空格隔开的整数A、B和D,表示存在一条长度为 D(1 <= D <= 5000)的路连接农场A和农场B
Output
* 第1行: 输出一个整数,即从农场1到农场N的第二短路的长度
Sample Input
4 4
1 2 100
2 4 200
2 3 250
3 4 100
Sample Output
450
//最短路:1 -> 2 -> 4 (长度为100+200=300)
第二短路:1 -> 2 -> 3 -> 4 (长度为100+250+100=450)
这是道好题啊,相信大家第一秒看到觉得简单,稍加思考就懵逼了吧,不然也不会看到我这句话。
好了,说正经的:
这道题显然是spfa(虽然范围并不大,但是还是spfa)
其实和普通的spfa没什么两样,就是开一个存次短路的数组,然后在判断最短路径不是更优的时候判断一遍次短路径是否更优,如果是的,替换就行了
这里有一个点不得不说:在找到更优的最短路径的时候,原有的最短路径肯定变成了当前的次短路径(因为我们的目的就是在原有的最短路径上替换一条边,再使替换的这条边最短),所以我们每更新一次最短路,就要连次短路一起更新,精髓好好体会吧。
看代码(就多了一个数组和一个if):
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 int sum,n,m,q[5001],last[5001]; 6 bool used[5001]; 7 long long dis[5001],dis2[5001]; 8 struct data 9 { 10 int a,next,v; 11 }f[200001]; 12 void ins(int u,int v,int w) 13 { 14 sum++; 15 f[sum].a=v; 16 f[sum].v=w; 17 f[sum].next=last[u]; 18 last[u]=sum; 19 } 20 int main() 21 { 22 int t=0,w=1,now,i,u,v,x; 23 scanf("%d%d",&n,&m); 24 for(int i=1;i<=n;i++)dis[i]=dis2[i]=1e15; 25 for(int i=1;i<=m;i++) 26 scanf("%d%d%d",&u,&v,&x),ins(u,v,x),ins(v,u,x); 27 q[0]=1,used[1]=1,dis[1]=0; 28 while(t!=w) 29 { 30 now=q[t++]; 31 if(t==n)t=0; 32 for(i=last[now];i;i=f[i].next) 33 { 34 if(dis[now]+f[i].v<dis[f[i].a]) 35 { 36 dis2[f[i].a]=dis[f[i].a];//在找到更优的最短路径的时候,原有的最短路径肯定变成了当前的次短路径 37 dis[f[i].a]=dis[now]+f[i].v; 38 if(!used[f[i].a]) 39 { 40 used[f[i].a]=1; 41 q[w++]=f[i].a; 42 if(w==n)w=0; 43 } 44 } 45 else if(dis[now]+f[i].v<dis2[f[i].a]&&dis[now]+f[i].v>dis[f[i].a]) 46 { 47 dis2[f[i].a]=dis[now]+f[i].v; 48 if(!used[f[i].a]) 49 { 50 used[f[i].a]=1; 51 q[w++]=f[i].a; 52 if(w==n)w=0; 53 } 54 } 55 if(dis2[now]+f[i].v<dis2[f[i].a]) 56 { 57 dis2[f[i].a]=dis2[now]+f[i].v; 58 if(!used[f[i].a]) 59 { 60 used[f[i].a]=1; 61 q[w++]=f[i].a; 62 if(w==n)w=0; 63 } 64 } 65 } 66 used[now]=0; 67 } 68 if(dis2[n]!=1e15)printf("%d",dis2[n]); 69 else printf("-1"); 70 }