有一個郵遞員要送東西,郵局在節點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.