邮递员送信(luogu 1629)题解
【问题描述】
有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间。这个邮递员每次只能带一样东西。求送完这N-1样东西并且最终回到邮局最少需要多少时间。
【样例输入】
5 10
2 3 5
1 5 5
3 5 6
1 2 8
1 3 8
5 3 4
4 1 8
4 5 3
3 5 6
5 4 2
【样例输出】
83
【解题思路】
看到这题……这不明摆着赤裸裸的最短路嘛,而且还要往返走,还是单向的,n<=1000,还用说什么?邻接矩阵+floyed搞起啊!然而……交上OJ后发现,仅仅AC了4个点……TLE6个……算了算复杂度,嗯……不错,最大可以到O(10^9)不爆才怪了……于是换一种思路……那么只能求单源最短路了,怎么求呢?两边dijkstra一边算过去的,一边算回来的……然后顺便注意一下重边,于是AC了……
下面我们来总结一下求最短路的方法,求多源最短路……不用说,只能floyed,如果数据给大了的话肯定就是你想错了,比如今天这道题……由一点出发回到同一点的题可以看做单源最短路,如果没有负权边的话能用dijkstra尽量用dijkstra,(自我感觉dijkstra最好写……)当然愿意写SPFA是最佳选择,SPFA的时间复杂度是最低的。然后,对于存储图的问题,能用邻接矩阵尽量用邻接矩阵,邻接矩阵比邻接表还是方便许多的,(便于debug,便于观察),如果实在不行的话那就只能用邻接表了,愿意用邻接表的用邻接表也可以。(自我感觉不愿意去写……)
【代码实现】
1 var a:array[-1..1010,-1..1010] of longint; 2 i,j,n,m,u,v,w,ans,k:longint; 3 f:array[-1..1010] of boolean; 4 s1,s2:array[-1..1010] of longint; 5 procedure dijkstra; 6 var i,j,min,pos:longint; 7 begin 8 f[1]:=true; 9 for i:=2 to n do 10 begin 11 min:=maxlongint; 12 pos:=-1; 13 for j:=1 to n do 14 if not(f[j])and(s1[j]<min) then 15 begin 16 min:=s1[j]; 17 pos:=j; 18 end; 19 if pos=-1 then 20 break; 21 f[pos]:=true; 22 for j:=1 to n do 23 if not(f[j])and(s1[pos]+a[pos,j]<s1[j]) then 24 s1[j]:=s1[pos]+a[pos,j]; 25 end; 26 end; 27 procedure dijkstra1; 28 var i,j,min,pos:longint; 29 begin 30 f[1]:=true; 31 for i:=2 to n do 32 begin 33 min:=maxlongint; 34 pos:=-1; 35 for j:=1 to n do 36 if not(f[j])and(s2[j]<min) then 37 begin 38 min:=s2[j]; 39 pos:=j; 40 end; 41 if pos=-1 then 42 break; 43 f[pos]:=true; 44 for j:=1 to n do 45 if not(f[j])and(s2[pos]+a[j,pos]<s2[j]) then 46 s2[j]:=s2[pos]+a[j,pos]; 47 end; 48 end; 49 begin 50 readln(n,m); 51 for i:=1 to n do 52 for j:=1 to n do 53 a[i,j]:=maxint+100000; 54 for i:=2 to n do 55 begin 56 s1[i]:=maxint+100000; 57 s2[i]:=maxint+100000; 58 end; 59 for i:=1 to m do 60 begin 61 readln(u,v,w); 62 if w<a[u,v] then 63 a[u,v]:=w; 64 if (u=1)and(w<s1[v]) then 65 s1[v]:=w; 66 if (v=1)and(w<s2[u]) then 67 s2[u]:=w; 68 end; 69 dijkstra; 70 fillchar(f,sizeof(f),false); 71 dijkstra1; 72 for i:=2 to n do 73 ans:=ans+s1[i]+s2[i]; 74 writeln(ans); 75 end.