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.

转载于:https://www.cnblogs.com/HAdolf-HQY/p/6758100.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值