题意: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