Flows, Matchings & Path Covers¶
Max flow (Ford–Fulkerson idea)¶
Directed graph with capacity on edges, source s, sink t. Augment paths while residual capacity remains; DFS or BFS (Edmonds–Karp) finds augmenting paths.
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
bool bfsFlow(int s, int t, const vector<vector<int>>& cap, vector<vector<int>>& flow,
vector<int>& parent) {
int n = (int)cap.size();
fill(parent.begin(), parent.end(), -1);
vector<bool> vis(n, false);
queue<int> q;
vis[s] = true;
q.push(s);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v = 0; v < n; v++) {
int residual = cap[u][v] - flow[u][v];
if (!vis[v] && residual > 0) {
vis[v] = true;
parent[v] = u;
if (v == t) return true;
q.push(v);
}
}
}
return false;
}
int maxFlowEdmondsKarp(int s, int t, vector<vector<int>> cap) {
int n = (int)cap.size();
vector<vector<int>> flow(n, vector<int>(n, 0));
vector<int> parent(n);
int total = 0;
while (bfsFlow(s, t, cap, flow, parent)) {
int add = 1e9;
for (int v = t; v != s; v = parent[v]) {
int u = parent[v];
add = min(add, cap[u][v] - flow[u][v]);
}
for (int v = t; v != s; v = parent[v]) {
int u = parent[v];
flow[u][v] += add;
flow[v][u] -= add;
}
total += add;
}
return total;
}
For large graphs use Dinic or push-relabel; for bipartite matching, Hopcroft–Karp is common.
Bipartite matching¶
Left–right bipartition; max matching equals max flow from super-source to super-sink with unit capacities, or specialized augmenting-path algorithms.
König’s theorem (bipartite)¶
In bipartite graphs, size of minimum vertex cover = size of maximum matching; complement gives maximum independent set on that side’s structure.
Path cover in DAG¶
Minimum path cover (vertex-disjoint paths covering all vertices) in a DAG: build bipartite graph \((u_{left}, v_{right})\) for each edge \(u \to v\); answer = \(|V|\) − max matching on that bipartite graph.
Related¶
- Graph basics — residual network idea
- Union-Find — unrelated to flow, but often in same contests