CodeVS 1269-匈牙利游戏
原题
题目描述 Description
欢迎来到匈牙利游戏!布达佩斯(匈牙利首都)的街道形成了一个弯曲的单向网络。
你被强制要求参加一个赛跑作为一个TV秀的一部分节目,比赛中你需要穿越这些街道,从s开始,到t结束。
很自然的,你想要尽快的完成比赛,因为你的比赛完成的越好,你就能得到更多的商业促销合同。
但是,有一个需要了解的是,如果有人过于聪明找到从s到t的最短路线,那么他就被扔到国家极品人类保护系统中作为一个国家宝藏收藏起来。你显然要避免这种事情的发生,但是也想越快越好。写一个程序来计算一个从s到t的严格次短路线吧。
有的时候,严格次短路线可能访问某些节点不止一次。样例2是一个例子。
输入描述 Input Description
第一行包含两个整数N和M,N代表布达佩斯的节点个数,M代表边的个数。节点编号从1到N。1代表出发点s,N代表终点t。接下来的M行每行三个整数A B L,代表有一条从A到B的长度为L的单向同路。你可以认为A不等于B,也不会有重复的(A,B)对。
输出描述 Output Description
输出从s到t的严格次短路的长度。如果从s到t的路少于2条,输出-1。
样例输入 Sample Input
样例输入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
样例输出 Sample Output
样例输出1:
11
样例输出2:
3
数据范围及提示 Data Size & Hint
对于样例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.
题解
实际上就是求次短路,用SPFA来解决。
维护两个数组,一个储存最短路,另一个储存次短路,一边求最短路一边求次短路。
每次更新最短路和次短路有3种情况:
1.当到x的最短路可以更新到y的最短路的时候,到y的次短路更新为原来到y的最短路,到y的最短路更新为到x的最短路加上xy的距离;
2.当到x的最短路不能更新到y的最短路,但可以更新到y的次短路,并且到x的最短路+xy的距离不等于到y的最短路(如果相等的话,那么到y的次短路和最短路是一样的,于是错乱),则用更新到y的次短路;
3.当到x的最短路不能更新到y的最短路,也不能更新到y的次短路,但到x的次短路能更新到y的次短路,就更新它。
最后输出到n的次短路就是答案。
代码:
var q,ne,b,c:array[1..1000000] of longint;
var d1,d2,fir:array[1..100000] of int64;
var us:array[1..100000] of boolean;
var n,m,i,tot,x,y,z:longint;
procedure add(x,y,z:longint); begin inc(tot);b[tot]:=y;c[tot]:=z;ne[tot]:=fir[x];fir[x]:=tot; end;//邻接表
procedure spfa(s:longint);//最短路与次短路
var i,j,u,h,w,t,v:longint;
begin
d1[s]:=0;us[s]:=true;h:=1;t:=1;q[1]:=s;
while h<=t do
begin
u:=q[h];j:=fir[u];
while j>0 do
begin
v:=b[j];w:=c[j];
if d1[v]>d1[u]+w then
begin
d2[v]:=d1[v];d1[v]:=d1[u]+w;
if not us[v] then begin inc(t);q[t]:=v;us[v]:=true; end;
end else
if (d1[u]+w<>d1[v])and(d2[v]>d1[u]+w) then
begin
d2[v]:=d1[u]+w;
if not us[v] then begin inc(t);q[t]:=v;us[v]:=true; end;
end else
if d2[v]>d2[u]+w then
begin
d2[v]:=d2[u]+w;
if not us[v] then begin inc(t);q[t]:=v;us[v]:=true; end;
end;
j:=ne[j];
end;
inc(h);us[u]:=false;
end;
end;
begin
readln(n,m);
for i:=1 to m do begin readln(x,y,z);add(x,y,z); end;
for i:=1 to n do begin d1[i]:=maxlongint;d2[i]:=maxlongint; end;
spfa(1);
if d2[n]=maxlongint then writeln(-1) else writeln(d2[n]);
end.