-
Notifications
You must be signed in to change notification settings - Fork 1
/
mcf_graph.hpp
62 lines (56 loc) · 1.79 KB
/
mcf_graph.hpp
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
#pragma once
#include "../template/template.hpp"
namespace lib {
using namespace std;
struct MinCostFlow {
int n;
vector<vector<vector<ll>>> g;
vector<ll> h, dis;
vector<int> pv, pe;
MinCostFlow(int v) : n(v), g(v), dis(v), pv(v), pe(v) {}
void add_edge(int from, int to, ll cap, ll cost) {
g[from].push_back({to, cap, cost, (int)g[to].size()});
g[to].push_back({from, 0, -cost, (int)g[from].size()-1});
}
ll flow(int s, int t, ll f) {
ll res = 0;
h.assign(n, 0);
using Q = pair<ll, int>;
while (f > 0) {
priority_queue<Q, vector<Q>, greater<Q>> que;
dis.assign(n, LLONG_MAX);
dis[s] = 0;
que.push({0, s});
while (que.size()) {
Q q = que.top();
int v = q.second;
que.pop();
if (dis[v] < q.first) continue;
rep(i,0,g[v].size()){
auto edge = g[v][i];
int to = edge[0];
ll cap = edge[1], cost = edge[2];
if (cap > 0 and dis[to] > dis[v] + cost + h[v] - h[to]) {
dis[to] = dis[v] + cost + h[v] - h[to];
pv[to] = v;
pe[to] = i;
que.push({dis[to], to});
}
}
}
if (dis[t] == LLONG_MAX) return -1;
rep(i,0,n) h[i] += dis[i];
ll d = f;
for (int i=t; i!=s; i=pv[i]) d = min(d, g[pv[i]][pe[i]][1]);
f -= d;
res += d * h[t];
for (int i=t; i!=s; i=pv[i]) {
auto& edge = g[pv[i]][pe[i]];
edge[1] -= d;
g[i][edge[3]][1] += d;
}
}
return res;
}
};
}