struct max_flow_graph {
struct edge {
int u, v, cap, flow;
};
int n;
vector<edge> el;
vector<vector<int>> adj;
vector<int> dist, par;
max_flow_graph(int n) : n(n), adj(n) {}
void add_edge(int u, int v, int w) {
adj[u].push_back(el.size());
el.push_back({u, v, w, 0});
adj[v].push_back(el.size());
el.push_back({v, u, 0, 0});
}
int send_one_flow(int s, int e) {
int nf = INF;
for (int u = e; u != s; u = el[par[u]].u) {
nf = min(nf, el[par[u]].cap - el[par[u]].flow);
}
for (int u = e; u != s; u = el[par[u]].u) {
el[par[u]].flow += nf;
el[par[u]^1].flow -= nf;
}
return nf;
}
bool bfs(int s, int e) {
dist.assign(n, INT_MAX);
par.assign(n, 0);
queue<int> q;
q.push(s); dist[s] = 0;
while (q.size()) {
int u = q.front(); q.pop();
if (u == e) break;
for (int idx : adj[u]) {
if (el[idx].cap > el[idx].flow && dist[el[idx].v] > dist[el[idx].u] + 1) {
dist[el[idx].v] = dist[el[idx].u] + 1;
par[el[idx].v] = idx;
q.push(el[idx].v);
}
}
}
return dist[e] < INF;
}
long long edmonds_karp(int s, int e) {
long long mf = 0;
while (bfs(s, e)) mf += send_one_flow(s, e);
return mf;
}
};