Add graph/mcmf.cc
Signed-off-by: subcrip <contact@subc.rip>
This commit is contained in:
parent
dc51877945
commit
3809174648
|
@ -0,0 +1,77 @@
|
||||||
|
struct mcmf {
|
||||||
|
struct edge {
|
||||||
|
int to;
|
||||||
|
ll cap;
|
||||||
|
ll flow;
|
||||||
|
ll cost;
|
||||||
|
int rev;
|
||||||
|
};
|
||||||
|
|
||||||
|
vector<vector<edge>> edges;
|
||||||
|
vector<ll> dis;
|
||||||
|
vector<bool> vis;
|
||||||
|
ll ret;
|
||||||
|
|
||||||
|
mcmf(int n) : edges(n + 1), dis(n + 1), vis(n + 1) {}
|
||||||
|
|
||||||
|
void add_edge(int from, int to, ll cap, ll cost) {
|
||||||
|
edges[from].push_back({ to, cap, 0, cost, int(edges[to].size()) });
|
||||||
|
edges[to].push_back({ from, 0, 0, -cost, int(edges[from].size() - 1)});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sp(int s, int t) {
|
||||||
|
dis.assign(edges.size(), INFLL);
|
||||||
|
dis[s] = 0;
|
||||||
|
int n = edges.size();
|
||||||
|
int f = 1;
|
||||||
|
while (f) {
|
||||||
|
f = 0;
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
for (auto&& [to, cap, flow, cost, rev] : edges[i]) {
|
||||||
|
if (cap > flow and dis[to] > dis[i] + cost) {
|
||||||
|
dis[to] = dis[i] + cost;
|
||||||
|
f = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dis[t] != INFLL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ll dfs(int s, int t, ll cap) {
|
||||||
|
if (vis[s]) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
vis[s] = 1;
|
||||||
|
if (s == t) {
|
||||||
|
return cap;
|
||||||
|
}
|
||||||
|
ll res = 0;
|
||||||
|
int n = edges[s].size();
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
auto e = edges[s][i];
|
||||||
|
if (e.cap > e.flow and dis[e.to] == dis[s] + e.cost) {
|
||||||
|
ll nw = dfs(e.to, t, min(cap - res, e.cap - e.flow));
|
||||||
|
edges[s][i].flow += nw;
|
||||||
|
edges[e.to][e.rev].flow -= nw;
|
||||||
|
res += nw;
|
||||||
|
ret += nw * e.cost;
|
||||||
|
if (res == cap) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns: (flow, cost)
|
||||||
|
pll run(int s, int t) {
|
||||||
|
ll res = 0; ret = 0;
|
||||||
|
while (sp(s, t)) {
|
||||||
|
vis.assign(edges.size(), 0);
|
||||||
|
ll curr = dfs(s, t, LLONG_MAX);
|
||||||
|
res += curr;
|
||||||
|
}
|
||||||
|
return { res, ret };
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue