描述
当多多的朋友在农场拜访他时,他喜欢带他们参观。
他的农场包括N(1 <= N <= 1000)个编号为1...N的田地,第1个是多多的房子,第N个是谷仓。
总共M(1 <= M <= 10000)条路径以各种方式连接地点。每条路径连接两个不同的地点,并且长度小于35000,且非零。
多多带朋友们游览,从他的房子开始,可能经过某些地点,然后在谷仓结束。然后,他再回到了他的房子(可能经过一些田地)。
多多不想在任何给定的路径上重复访问,但希望参观的行程尽可能短。因此,计算最短行程的长度。
解题思路:最小费用最大流。
输入
第1行:两个以空格分隔的整数:N和M。
第2..M + 1行:定义路径的三个以空格分隔的整数:起始地点编号,结束地点编号和路径的长度。
注意:两个地点之间可能存在多条路径。
输出
多多的最短行程的长度
输入样例 1
4 5
1 2 1
2 3 1
3 4 1
1 3 2
2 4 2
输出样例 1
6
输入样例 2
2 2
1 2 1
1 2 2
输出样例 2
3
输入样例 3
1 0
输出样例 3
0
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1010, INF = 0x3f3f3f3f;
int n, m;
int g[N][N];
int backup[N][N];
int dist[N];
int parent[N];
bool st[N];
int dijkstra(int start, int terminal)
{
memset(dist, 0x3f, sizeof dist);
dist[start] = 0;
for (int i = 1; i < n; i++)
{
int t = -1;
for (int j = 1; j <= n; j++)
{
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
}
st[t] = true;
for (int j = 1; j <= n; j++)
{
if (dist[j] > dist[t] + g[t][j])
{
parent[j] = t;
dist[j] = dist[t] + g[t][j];
}
}
}
return dist[terminal];
}
void update_path()
{
memset(st, false, sizeof st);
for (int i = n; i; i = parent[i])
{
int j = parent[i];
g[i][j] = g[j][i] = backup[i][j];
}
}
int main()
{
memset(g, 0x3f, sizeof g);
memset(backup, 0x3f, sizeof backup);
cin >> n >> m;
while (m--)
{
int a, b, w;
cin >> a >> b >> w;
if (a == b) w = INF;
backup[a][b] = backup[b][a] = max(g[a][b], w);
g[a][b] = g[b][a] = min(g[a][b], w);
}
int t1 = dijkstra(1, n);
// cout << dijkstra(1, n) << endl;
update_path();
int t2 = dijkstra(n, 1);
// cout << dijkstra(n, 1) << endl;
printf("%d\n", t1 + t2);
return 0;
}