【题意】
给定一个有向加权图,求s到f的最短路径和比最短路径长1的路径数
【输入】
多组数据,第一行一个数字t表示有多少组数据
每组数据第一行两个数n、m表示点的个数和边的个数(n<=1000,m<=10000)
接下来m行每行三个整数a、b、l表示存在一条长度为l连接a、b的有向边
最后一行两个整数s、f
【输出】
对于每组数据输出一行,该行一个整数表示路径数
heap+dijkstra
如果用A*的话会超时,因为最终答案是10^8等级的
每个点维护两个值,最小值和次小值,再加上计数即可,代码略显臃肿
program poj3463;
var
ans,tot,n,m,i,j,k,t,s,f,a,b,l:longint;
root:array [0..10001] of longint;
rank,count,dis:array [0..1,0..10001] of longint;
next,point,cost:array [0..100001] of longint;
heap,mode:array [0..20001] of longint;
procedure swap (var a,b:longint);
var
i:longint;
begin
i:=a;
a:=b;
b:=i;
end;
procedure connect (a,b,l:longint);
begin
inc(tot);
point[tot]:=b;
cost[tot]:=l;
next[tot]:=root[a];
root[a]:=tot;
end;
procedure insert (o,now:longint);
var
i:longint;
begin
inc(tot);
heap[tot]:=now;
mode[tot]:=o;
rank[o,now]:=tot;
i:=tot;
while (i>1)and(dis[mode[i div 2],heap[i div 2]]>dis[o,now]) do
begin
swap(rank[mode[i div 2],heap[i div 2]],rank[o,now]);
swap(mode[i div 2],mode[i]);
swap(heap[i div 2],heap[i]);
i:=i div 2;
end;
end;
procedure delete (o,now:longint);
var
i:longint;
begin
if rank[o,now]=0 then exit;
if rank[o,now]=tot then
begin
heap[tot]:=0;
mode[tot]:=0;
rank[o,now]:=0;
dec(tot);
exit;
end;
i:=rank[o,now];
swap(rank[o,now],rank[mode[tot],heap[tot]]);
swap(heap[i],heap[tot]);
swap(mode[i],mode[tot]);
rank[o,now]:=0;
heap[tot]:=0;
mode[tot]:=0;
dec(tot);
if (i>1)and(dis[mode[i div 2],heap[i div 2]]>dis[mode[i],heap[i]]) then
while (i>1)and(dis[mode[i div 2],heap[i div 2]]>dis[mode[i],heap[i]]) do
begin
swap(rank[mode[i div 2],heap[i div 2]],rank[mode[i],heap[i]]);
swap(mode[i],mode[i div 2]);
swap(heap[i],heap[i div 2]);
i:=i div 2;
end
else
while (dis[mode[i*2],heap[i*2]]<dis[mode[i],heap[i]])or
(dis[mode[i*2+1],heap[i*2+1]]<dis[mode[i],heap[i]]) do
if dis[mode[i*2],heap[i*2]]<dis[mode[i*2+1],heap[i*2+1]] then
begin
swap(rank[mode[i * 2],heap[i * 2]],rank[mode[i],heap[i]]);
swap(mode[i],mode[i * 2]);
swap(heap[i],heap[i * 2]);
i:=i * 2;
end
else
begin
swap(rank[mode[i * 2 + 1],heap[i * 2 + 1]],rank[mode[i],heap[i]]);
swap(mode[i],mode[i * 2 + 1]);
swap(heap[i],heap[i * 2 + 1]);
i:=i * 2 + 1;
end
end;
procedure spfa;
var
who,now,i,j,k:longint;
begin
while tot>0 do
begin
who:=heap[1];
now:=mode[1];
delete(now,who);
k:=root[who];
while k<>0 do
begin
if dis[now,who]+cost[k]<dis[0,point[k]] then
begin
swap(dis[0,point[k]],dis[1,point[k]]);
count[1,point[k]]:=count[0,point[k]];
dis[0,point[k]]:=dis[now,who]+cost[k];
count[0,point[k]]:=count[now,who];
delete(0,point[k]);
delete(1,point[k]);
insert(0,point[k]);
insert(1,point[k]);
end
else
if dis[now,who]+cost[k]=dis[0,point[k]] then
count[0,point[k]]:=count[0,point[k]]+count[now,who]
else
if dis[now,who]+cost[k]<dis[1,point[k]] then
begin
dis[1,point[k]]:=dis[now,who]+cost[k];
count[1,point[k]]:=count[now,who];
delete(1,point[k]);
insert(1,point[k]);
end
else
if dis[now,who]+cost[k]=dis[1,point[k]] then
count[1,point[k]]:=count[1,point[k]]+count[now,who];
k:=next[k];
end;
end;
end;
begin
read(t);
while t>0 do
begin
fillchar(root,sizeof(root),0);
fillchar(heap,sizeof(heap),0);
fillchar(mode,sizeof(mode),0);
fillchar(dis,sizeof(dis),63);
fillchar(count,sizeof(count),0);
tot:=0;
read(n,m);
for i:=1 to m do
begin
read(a,b,l);
connect(a,b,l);
end;
read(s,f);
tot:=0;
dis[0,s]:=0;
count[0,s]:=1;
insert(0,s);
spfa;
ans:=count[0,f];
if dis[0,f]+1=dis[1,f] then ans:=ans+count[1,f];
writeln(ans);
dec(t);
end;
end.