题目来源:http://poj.org/problem?id=2135
Dijkstra算法实现:https://blog.csdn.net/moon_sky1999/article/details/81360017
抽象为每条边的费用为边的长度,流量为1,这样即是求1-n流量为2的最小费用流。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxm=1e5+10;
const int maxn=1e4+10;
int n,m;
int cnt,head[maxn],dis[maxn],prevv[maxn],preve[maxn];
struct edge {
int to, next, cap, cost, rev;
}e[maxm];
void ins(int x,int y,int z,int c) {
e[++cnt].to = y;
e[cnt].next = head[x];
head[x] = cnt;
e[cnt].cap = z;
e[cnt].rev = cnt + 1;
e[cnt].cost = c;
e[++cnt].to = x;
e[cnt].next = head[y];
head[y] = cnt;
e[cnt].cap = 0;
e[cnt].rev = cnt - 1;
e[cnt].cost = -c;
}
int min_cost_flow(int s,int t,int f) {
int ans = 0;
while (f > 0) {
memset(dis, 63, sizeof(dis));
queue<int> q;
q.push(s);
dis[s] = 0;
while (!q.empty()) {
int v = q.front();
q.pop();
if (dis[v] > 1e8)continue;
for (int i = head[v]; i; i = e[i].next) {
if (e[i].cap > 0 && dis[e[i].to] > dis[v] + e[i].cost) {
dis[e[i].to] = dis[v] + e[i].cost;
prevv[e[i].to] = v;
preve[e[i].to] = i;
q.push(e[i].to);
}
}
}
if (dis[t] > 1e8)
return -1;
int d = f;
for (int i = t; i != s; i = prevv[i]) {
d = min(d, e[preve[i]].cap);
}
f -= d;
ans += d * dis[t];
for (int i = t; i != s; i = prevv[i]) {
e[preve[i]].cap -= d;
e[e[preve[i]].rev].cap += d;
}
}
return ans;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
while (cin >> n >> m) {
cnt = 0;
memset(head, 0, sizeof(head));
memset(preve, 0, sizeof(preve));
memset(prevv, 0, sizeof(prevv));
for (int i = 1; i <= m; ++i) {
int x, y, z;
cin >> x >> y >> z;
ins(x, y, 1, z);
ins(y, x, 1, z);
}
cout << min_cost_flow(1, n, 2) << endl;
}
return 0;
}