codevs 1269 匈牙利游戏(次短路)
Welcome to the Hungary Games! The streets of Budapest form a twisted network of one-way streets.
欢迎来到匈牙利游戏!布达佩斯(匈牙利首都)的街道形成了一个弯曲的单向网络。
You have been forced to join a race as part of a “Reality TV” show where you race through these streets, starting at the Sz´echenyi thermal bath (s for short) and ending at the Tomb of G¨ ul Baba (t for short).
你被强制要求参加一个赛跑作为一个TV秀的一部分节目,比赛中你需要穿越这些街道,从s开始,到t结束。
Naturally, you want to complete the race as quickly as possible, because you will get more promo- tional contracts the better you perform.
很自然的,你想要尽快的完成比赛,因为你的比赛完成的越好,你就能得到更多的商业促销合同。
However, there is a catch: any person who is smart enough to take a shortest s-t route will be thrown into the P´alv¨olgyi cave system and kept as a national treasure. You would like to avoid this fate, but still be as fast as possible. Write a program that computes a strictly-second-shortest s-t route.
但是,有一个需要了解的是,如果有人过于聪明找到从s到t的最短路线,那么他就被扔到国家极品人类保护系统中作为一个国家宝藏收藏起来。你显然要避免这种事情的发生,但是也想越快越好。写一个程序来计算一个从s到t的严格次短路线吧。
Sometimes the strictly-second-shortest route visits some nodes more than once; see Sample Input 2 for an example.
有的时候,严格次短路线可能访问某些节点不止一次。样例2是一个例子。
The first line will have the format N M, where N is the number of nodes in Budapest and M is the number of edges. The nodes are 1,2,...,N; node 1 represents s; node N represents t. Then there are M lines of the form A B L, indicating a one-way street from A to B of length L. You can assume that A != B on these lines, and that the ordered pairs (A,B) are distinct.
第一行包含两个整数N和M,N代表布达佩斯的节点个数,M代表边的个数。节点编号从1到N。1代表出发点s,N代表终点t。接下来的M行每行三个整数A B L,代表有一条从A到B的长度为L的单向同路。你可以认为A不等于B,也不会有重复的(A,B)对。
Output the length of a strictly-second-shortest route from s to t. If there are less than two possible lengths for routes from s to t, output −1.
输出从s到t的严格次短路的长度。如果从s到t的路少于2条,输出-1。
样例输入1:
4 6
1 2 5
1 3 5
2 3 1
2 4 5
3 4 5
1 4 13
样例输入2:
2 2
1 2 1
2 1 1
样例输出1:
11
样例输出2:
3
对于样例1:
There are two shortest routes of length 10 (1 → 2 → 4,1 → 3 → 4) and the strictly-second- shortest route is 1 → 2 → 3 → 4 with length 11.
对于样例2:
The shortest route is 1 → 2 of length 1, and the strictly-second route is 1 → 2 → 1 → 2 of length 3.
另一种思路见:http://blog.csdn.net/cax1165/article/details/52129959
/* 借鉴别人的思路 建立正向图和反向图,分别SPFA一次,从起点和终点到各个点的最短路,其中正向图SPFA时记录下最短路径经过的点、构造邻接表(注意:最短路径可能不只一条,且可能相互重合) 对于最短路径经过的每一个点(设为u),枚举其指向的点(设为v)(当两点在同一最短路时不枚举),ans=MAX(u到s距离+uv距离+v到t距离) */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #define maxn 2000100 #define maxx 100100 using namespace std; int n,m,topt,ans,ans2,dis2[maxx],dis1[maxx],first[maxx],f[maxx],head[maxx]; queue<int>q; struct edge { int from; int to; int val; int next; }e[maxn],e2[maxn]; void add(int x,int y,int z) { topt++; e[topt].from=x; e[topt].to=y; e[topt].val=z; e[topt].next=first[x]; first[x]=topt; e2[topt].from=y; e2[topt].to=x; e2[topt].val=z; e2[topt].next=head[y]; head[y]=topt; } void SPFA() { memset(dis1,9,sizeof(dis1)); memset(f,0,sizeof(f)); ans=ans2=dis1[0]; q.push(1); dis1[1]=0; f[1]=1; while(!q.empty()) { int u=q.front(); q.pop(); f[u]=0; for(int i=first[u];i;i=e[i].next) { int t=e[i].to; if(dis1[t]>dis1[u]+e[i].val) { dis1[t]=dis1[u]+e[i].val; if(!f[t]) { q.push(t); f[t]=1; } } } } } void spfa() { memset(dis2,9,sizeof(dis2)); memset(f,0,sizeof(f)); q.push(n); dis2[n]=0; f[n]=1; while(!q.empty()) { int u=q.front(); q.pop(); f[u]=0; for(int i=head[u];i;i=e2[i].next) { int t=e2[i].to; if(dis2[t]>dis2[u]+e2[i].val) { dis2[t]=dis2[u]+e2[i].val; if(!f[t]) { q.push(t); f[t]=1; } } } } } int main() { int i,j,k; scanf("%d%d",&n,&m); for(i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z); } SPFA(); spfa(); for(i=1;i<=topt;i++) { int f,t,v,p,q; f=e[i].from,t=e[i].to,v=e[i].val; p=dis1[f];q=dis2[t]; if(p+v+q<0)continue; if(ans>p+v+q)ans2=ans,ans=p+v+q; else if(ans<p+v+q&&ans2>p+v+q)ans2=p+v+q; } if(ans2>=dis1[0])printf("-1\n"); else printf("%d\n",ans2); return 0; }