Skip to Content
Team NoteAlgorithmMCMF

MCMF

struct Edge { int from, to, c, f = 0, spare, cost; Edge *rev; Edge(int from, int to, int c, int cost) : from(from), to(to), c(c), cost(cost) { spare = c; } Edge(int from, int to, int c, int cost, Edge *rev) : Edge(from, to, c, cost) { this->rev = rev; rev->rev = this; } void add_capacity(int capacity, int capacity_rev = 0) { c += capacity; spare += capacity; if (capacity_rev != 0) rev->add_capacity(capacity_rev, 0); } void add_flow(int v) { f += v; rev->f -= v; spare -= v; rev->spare += v; } }; typedef vector<Edge *> ve; const int INF = 2e9; class MCMF { private: int n, source, sink; public: vector<ve> edges; MCMF(int n, int source, int sink) : n(n), source(source), sink(sink) { edges.resize(n); } void add_edge(int i, int j, int c, int c_rev, int cost) { Edge *e = new Edge(i, j, c, cost); Edge *e_rev = new Edge(j, i, c_rev, -cost, e); edges[i].pb(e); edges[j].pb(e_rev); } pi flow() { int max_flow = 0; ll cost_sum = 0; while (1) { vi from(n, -1), in_q(n, false), d(n, INF); ve path(n, 0); queue<int> q; q.push(source); in_q[source] = true; d[source] = 0; while (sz(q)) { // SPFA int cur = q.front(); q.pop(); in_q[cur] = false; for (Edge *e: edges[cur]) { if (e->spare > 0 && d[e->to] > d[cur] + e->cost) { d[e->to] = d[cur] + e->cost; from[e->to] = cur; path[e->to] = e; if (!in_q[e->to]) { q.push(e->to); in_q[e->to] = true; } } } } if (from[sink] == -1) break; int min_flow = INF; for (int i = sink; i != source; i = from[i]) min_flow = min(min_flow, path[i]->spare); for (int i = sink; i != source; i = from[i]) { path[i]->add_flow(min_flow); cost_sum += min_flow * path[i]->cost; } max_flow += min_flow; } return {max_flow, cost_sum}; } };
Last updated on