郵遞員送信(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.  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章