邮递员送信(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.  

 

你可能感兴趣的:(邮递员送信(luogu 1629)题解)