题目
有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间。这个邮递员每次只能带一样东西。求送完这N-1样东西并且最终回到邮局最少需要多少时间。
题解
首先用Floyd肯定会超时,然后用Dij每个点求一遍也肯定会超时,因为这都是
n3
所以我们先用Dij求一次从起点到其他所有点的路径和,
然后把所有边反过来,再求一遍从起点到其他点的路径和(求从每个点回到起点的路径和,理解不了就画一下图)
最终的时间复杂度O(n2)
代码
type
arr=array[1..1000,1..1000]of longint;
var
n,m,i,j,x,y,ans:longint;
a,b:arr;
d:array[1..1000]of longint;
f:array[1..1000]of boolean;
procedure dij;
var
i,j,u,min:longint;
begin
fillchar(f,sizeof(f),true);
fillchar(d,sizeof(d),$7f);
for i:=2 to n do if f[i] then d[i]:=a[1,i];
repeat
u:=0;min:=d[1];
for i:=2 to n do
if f[i] and(d[i]<min) then
begin
min:=d[i];
u:=i;
end;
if u>0 then
begin
f[u]:=false;
ans:=ans+d[u];
for i:=2 to n do
if f[i] and(d[i]>d[u]+a[u,i]) then
d[i]:=d[u]+a[u,i];
end;
until u=0;
end;
procedure dij2;
var
i,j,u,min:longint;
begin
fillchar(f,sizeof(f),true);
fillchar(d,sizeof(d),$7f);
for i:=2 to n do if f[i] then d[i]:=b[1,i];
repeat
u:=0;min:=d[1];
for i:=2 to n do
if f[i] and(d[i]<min) then
begin
min:=d[i];
u:=i;
end;
if u>0 then
begin
f[u]:=false;
ans:=ans+d[u];
for i:=2 to n do
if f[i] and(d[i]>d[u]+b[u,i]) then
d[i]:=d[u]+b[u,i];
end;
until u=0;
end;
begin
readln(n,m);
fillchar(a,sizeof(a),$7f);
fillchar(b,sizeof(b),$7f);
for i:=1 to m do
begin
readln(x,y,j);
if a[x,y]>j then a[x,y]:=j;
if b[y,x]>j then b[y,x]:=j;
end;
dij;
dij2;
writeln(ans);
end.