邮递员送信(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.  
时间: 2024-08-23 23:46:33

邮递员送信(luogu 1629)题解的相关文章

codevs3872 邮递员送信(SPFA)

邮递员送信 时间限制: 1 Sec  内存限制: 64 MB提交: 10  解决: 5[提交][状态][讨论版] 题目描述 有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N.由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条 道路,通过每条道路需要一定的时间.这个邮递员每次只能带一样东西.求送完这N-1样东西并且最终回到邮局最少需要多少时间. 输入 第一行包括两个整数N和M. 第2到第M+1行,每行三个数字U.V.W,表示从A到B有一条需要W时间的道路

洛谷 P1629 邮递员送信

P1629 邮递员送信 题目描述 有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N.由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间.这个邮递员每次只能带一样东西.求送完这N-1样东西并且最终回到邮局最少需要多少时间. 输入输出格式 输入格式: 第一行包括两个整数N和M. 第2到第M+1行,每行三个数字U.V.W,表示从A到B有一条需要W时间的道路. 满足1<=U,V<=N,1<=W<=10000,输入保

[题解]洛咕P1629 邮递员送信

链接 一个邮递员要从一号点到每个点再回来,求最短路 题目说一次只能去一个点,这样就简单了,求每个点最短路 怎么求回来的最短路?每个点跑一次dijkstra?这样会T 只要反向建边,再求点1到各点的最短路不就行了吗?(可以画个图手算一遍) 代码: #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<queue> using namesp

洛谷—— P1629 邮递员送信

https://www.luogu.org/problem/show?pid=1629 题目描述 有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N.由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间.这个邮递员每次只能带一样东西.求送完这N-1样东西并且最终回到邮局最少需要多少时间. 输入输出格式 输入格式: 第一行包括两个整数N和M. 第2到第M+1行,每行三个数字U.V.W,表示从A到B有一条需要W时间的道路. 满足

P1629 邮递员送信(未完成)

题目描述 有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N.由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间.这个邮递员每次只能带一样东西.求送完这N-1样东西并且最终回到邮局最少需要多少时间. 输入输出格式 输入格式: 第一行包括两个整数N和M. 第2到第M+1行,每行三个数字U.V.W,表示从A到B有一条需要W时间的道路. 满足1<=U,V<=N,1<=W<=10000,输入保证任意两点都能互相到达.

最短路 P1629 邮递员送信

传送门 其实这一道题还是比较不错的 这一道题的题意稍微转化一下就是邮递员要到一个节点 然后再返回 求最短路 这我们很显然是可以用dijkstra算法的 我们先按照题目中给的边(单向边) 跑一边最短路 接下来一步我们是要求从各个点出发到S的最短路 乍一看很复杂的样子 其实只需要把整张图的边全部倒过来存储 然后再从起点开始跑一边最短路就可以了! 下面是代码(其实敲起来还是很简单的 练练代码熟练度~) #include<bits/stdc++.h> #define pa pair<int,in

逆向思维 + 用并查集动态维护连通块的个数——Luogu P1197题解

题目大意: 给你一个 $ n $ 个点的图与 $ m $ 条边,接下来给出一个长度为 $ k $ 个整数,按照给出整数的顺序依次删掉对应编号的点,求出一开始的连通块的个数与接下来每次删除一个点后的连通块的个数.(连通块就是一个点集,这个集合里面的任意两个点都可以互相到达) 思路: 大体思路: 这个题目如果正向考虑会很难做,因为我们要每次维护一个不断删点的图的连通块个数是很难弄的.所以我们要倒着考虑.假如我们把删点的过程倒着考虑,就变成了从最后一个点往前添加进这个图里面的过程.所以这样问题就变成了

【luogu1629】快递员送信 (spfa)

luoguP1629 邮递员送信 是该好好巩固一下QAQ 刷水题使我快乐 论两信竞学生如何讨论一道黄题纠结半个小时 正反各跑一遍spfa 用1次SPFA找各个点到点1的最短路,然后开一个反向图,再用SPFA搜一下点1到反向图各个点的最短路,反向图中点1到各个点的最短路就是普通图中各个点到点1的最短路 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1000+5,inf=1e9; 4 int n,m,ans=0; 5

洛谷——P1821 [USACO07FEB]银牛派对Silver Cow Party

P1821 [USACO07FEB]银牛派对Silver Cow Party 题目描述 One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X ≤ N). A total of M (1 ≤ M ≤ 100,000) unidirectional (one-way roads co