题目描述
有一个邮递员要送东西,邮局在节点 1。他总共要送 n-1 样东西,其目的地分别是节点 2 到节点 n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n-1 样东西并且最终回到邮局最少需要的时间。
输入格式
第一行包括两个整数,n 和 m,表示城市的节点数量和道路数量。
第二行到第 (m+1) 行,每行三个整数,u,v,w表示从 u 到 v 有一条通过时间为 w 的道路。
输出格式
输出仅一行,包含一个整数,为最少需要的时间。
输入输出样例
输入 #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
输出 #1复制
83
思路:
关于这题,Dijkstra怎么写呢。题的意思是:求点1到其余所有点的最短路,及其余所有点到点1的最短路,之后求和
显然:求点1到其余所有点的最短路很简单,就是Dijkstra的原算法模板。那么所有点到点1的最短路怎么求呢?
于是,我有了一个大胆的想法——取反向图,再用Dijkstra的原模板求出反向图中点1到其余所有点的最短路。之后求和就行了
反向建边 Dijkstra原算法是单源多汇,即shortpath存的是从一个点到其他多个点的最短路径
而对于要求其他多个点到一个点的多源单汇,我们可以采取反向建边的思想(单路图),让原来的路变成相反的路,即使仍然是按照从起点开始更新其他点,但此时每条边的距离已经变成相反的了,这样求得距离就变成多到一的距离
AC CODE
#include <bits/stdc++.h>
using namespace std;
#define maxn 1005
#define inf 1e9 + 7
int n, m, vis[maxn], a[maxn][maxn], shortpath[maxn];
struct node
{
int w, num;
bool operator<(const node &a) const
{
return w > a.w;
}
};
priority_queue<node> p;
void Dijkstra(int v0)
{
fill(shortpath + 1, shortpath + n + 1, inf);
shortpath[v0] = 0;
p.push((node){shortpath[v0], v0});
while (!p.empty())
{
node m = p.top();
p.pop();
int k = m.num;
if (vis[k])
continue;
vis[k] = 1;
for (int i = 1; i <= n; i++)
{
if (shortpath[i] > shortpath[k] + a[k][i])
{
shortpath[i] = shortpath[k] + a[k][i];
p.push((node){shortpath[i], i});
}
}
}
}
void Dijkstra_over(int v0)
{
fill(shortpath + 1, shortpath + n + 1, inf);
fill(vis + 1, vis + n + 1, 0);
shortpath[v0] = 0;
p.push((node){shortpath[v0], v0});
while (!p.empty())
{
node m = p.top();
p.pop();
int k = m.num;
if (vis[k])
continue;
vis[k] = 1;
for (int i = 1; i <= n; i++)
{
if (shortpath[i] > shortpath[k] + a[i][k])
{
shortpath[i] = shortpath[k] + a[i][k];
p.push((node){shortpath[i], i});
}
}
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
if (i == j)
a[i][j] = 0;
else
a[i][j] = inf;
}
while (m--)
{
int i, j, w;
cin >> i >> j >> w;
a[i][j] = min(w, a[i][j]);
}
Dijkstra(1);
int ans = 0;
for (int i = 1; i <= n; i++)
ans += shortpath[i];
Dijkstra_over(1);
for (int i = 1; i <= n; i++)
ans += shortpath[i];
cout << ans;
return 0;
}
这里的Dijkstra使用了堆优化