poj 3463 最短路和次短路

9 篇文章 0 订阅
4 篇文章 0 订阅

题意:n个点,m条有向边,给定起点和终点,求出起点到终点最短路和比最短路长1的路径的总条数

dijkstra算法,邻接表建图

改进Dijkstra算法。将状态扩展到二维,第一维仍然是顶点编号,第二维分别用于记录最短路和次短路。
这样的数据有两个,dist[][2]记录距离,cnt[][2]计数。
更新状态时:
1)新值小于最短路径长:将最短路的相关数据赋予次短路,更新最短路径长,计数;
2)新值等于最短路径长:更新最短路径计数
3)新值大于最短路径长,小于次短路径长:更新次短路径长,计数
4)新值等于次短路径长:更新次短路径计数

注意dijkstra的外层循环i要循环2*n次(其实2*n-1即可)

找出需要更新的当前点时,比较的应该是tt而不是最短路和最短路比、次短路和次短路比,考试的时候手残没细想爆零了...mdzz

var
      t,l,n,m,ss,st,x,y,z:longint;
      i                  :longint;
      ans                :int64;
      vis                :array[0..1010,0..2] of boolean;
      last               :array[0..1010] of longint;
      pre,other,len      :array[0..10010] of longint;
      tot                :array[0..1010,0..2] of int64;
      dis                :array[0..1010,0..2] of longint;
procedure connect(x,y,z:longint);
begin
   inc(l);
   pre[l]:=last[x];
   last[x]:=l;
   other[l]:=y;
   len[l]:=z;
end;

procedure dijkstra;
var
        i,j,p,q,cur,tmp,tt:longint;
begin
   fillchar(dis,sizeof(dis),127);
   fillchar(vis,sizeof(vis),false);
   fillchar(tot,sizeof(tot),0);
   dis[ss,0]:=0; tot[ss,0]:=1;
   for i:=1 to 2*n do
   begin
      cur:=0; tmp:=2; tt:=maxlongint;
      for j:=1 to n do
      begin
         if not vis[j,0] and (dis[j,0]<tt) then
         begin
            cur:=j; tmp:=0; tt:=dis[j,0];
         end else
         if not vis[j,1] and (dis[j,1]<tt) then
         begin
            cur:=j; tmp:=1; tt:=dis[j,1];
         end;
      end;
         if tmp=2 then break;
         vis[cur,tmp]:=true;
         q:=last[cur];
         while (q<>0) do
         begin
            p:=other[q];
            if (dis[p,0]>tt+len[q]) then
            begin
               dis[p,1]:=dis[p,0];
               tot[p,1]:=tot[p,0];
               dis[p,0]:=tt+len[q];
               tot[p,0]:=tot[cur,tmp];
            end else
            if dis[p,0]=tt+len[q] then
            begin
               inc(tot[p,0],tot[cur,tmp]);
            end else
            if dis[p,1]>tt+len[q] then
            begin
               dis[p,1]:=tt+len[q];
               tot[p,1]:=tot[cur,tmp];
            end else
            if dis[p,1]=tt+len[q] then
            begin
               inc(tot[p,1],tot[cur,tmp]);
            end;
            q:=pre[q];
         end;
   end;
end;

begin
   //assign(input,'shorter.in');reset(input);
   //assign(output,'shorter.out');rewrite(output);
   read(t);
   while (t>0) do
   begin
      l:=0; dec(t); ans:=0;
      fillchar(last,sizeof(last),0);
      read(n,m);
      for i:=1 to m do
      begin
         read(x,y,z);
         connect(x,y,z);
      end;
      read(ss,st);
      dijkstra;
      ans:=tot[st,0];
      if dis[st,1]=dis[st,0]+1 then inc(ans,tot[st,1]);
      writeln(ans);
   end;
   //close(input); close(output);
end.

——by Eirlys

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值