-
Notifications
You must be signed in to change notification settings - Fork 109
/
Copy pathMin Cost Max Flow 1.cpp
111 lines (99 loc) · 3.42 KB
/
Min Cost Max Flow 1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//
// Minimum Cost Maximum Flow (Tomizawa, Edmonds-Karp's successive shortest path)
//
// Description:
// Given a directed graph G = (V,E) with nonnegative capacity c and cost w.
// The algorithm find a maximum s-t flow of G with minimum cost.
//
// Algorithm:
// Tomizawa (1971), and Edmonds and Karp (1972)'s
// successive shortest path algorithm,
// which is also known as the primal-dual method.
//
// Complexity:
// O(F m log n), where F is the amount of maximum flow.
// Caution: Probably does not support Negative Costs
// Negative cost is supported in an implementation named: mincostmaxflow2.cpp
#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(s) if (!(s)) { cout << __LINE__ << " " << #s << endl; exit(-1); }
const long long INF = 1e9;
struct graph {
typedef int flow_type;
typedef int cost_type;
struct edge {
int src, dst;
flow_type capacity, flow;
cost_type cost;
size_t rev;
};
vector<edge> edges;
void add_edge(int src, int dst, flow_type cap, cost_type cost) {
adj[src].push_back({src, dst, cap, 0, cost, adj[dst].size()});
adj[dst].push_back({dst, src, 0, 0, -cost, adj[src].size()-1});
}
int n;
vector<vector<edge>> adj;
graph(int n) : n(n), adj(n) { }
pair<flow_type, cost_type> min_cost_max_flow(int s, int t) {
flow_type flow = 0;
cost_type cost = 0;
for (int u = 0; u < n; ++u) // initialize
for (auto &e: adj[u]) e.flow = 0;
vector<cost_type> p(n, 0);
auto rcost = [&](edge e) { return e.cost + p[e.src] - p[e.dst]; };
for (int iter = 0; ; ++iter) {
vector<int> prev(n, -1); prev[s] = 0;
vector<cost_type> dist(n, INF); dist[s] = 0;
if (iter == 0) { // use Bellman-Ford to remove negative cost edges
vector<int> count(n); count[s] = 1;
queue<int> que;
for (que.push(s); !que.empty(); ) {
int u = que.front(); que.pop();
count[u] = -count[u];
for (auto &e: adj[u]) {
if (e.capacity > e.flow && dist[e.dst] > dist[e.src] + rcost(e)) {
dist[e.dst] = dist[e.src] + rcost(e);
prev[e.dst] = e.rev;
if (count[e.dst] <= 0) {
count[e.dst] = -count[e.dst] + 1;
que.push(e.dst);
}
}
}
}
} else { // use Dijkstra
typedef pair<cost_type, int> node;
priority_queue<node, vector<node>, greater<node>> que;
que.push({0, s});
while (!que.empty()) {
node a = que.top(); que.pop();
if (a.snd == t) break;
if (dist[a.snd] > a.fst) continue;
for (auto e: adj[a.snd]) {
if (e.capacity > e.flow && dist[e.dst] > a.fst + rcost(e)) {
dist[e.dst] = dist[e.src] + rcost(e);
prev[e.dst] = e.rev;
que.push({dist[e.dst], e.dst});
}
}
}
}
if (prev[t] == -1) break;
for (int u = 0; u < n; ++u)
if (dist[u] < dist[t]) p[u] += dist[u] - dist[t];
function<flow_type(int,flow_type)> augment = [&](int u, flow_type cur) {
if (u == s) return cur;
edge &r = adj[u][prev[u]], &e = adj[r.dst][r.rev];
flow_type f = augment(e.src, min(e.capacity - e.flow, cur));
e.flow += f; r.flow -= f;
return f;
};
flow_type f = augment(t, INF);
flow += f;
cost += f * (p[t] - p[s]);
}
return {flow, cost};
}
};