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

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 }

 

posted @ 2018-08-08 11:17  蒟蒻--lichenxi  阅读(215)  评论(0编辑  收藏  举报