Given a directed graph (flow network) with edge capacities, find the maximum possible flow from a source node to a sink node. Additionally, show how the maximum flow algorithm can be used to solve the bipartite matching problem.
Input:
# Adjacency list for the graph below(Python format):adj =[[(1,3),(4,10)],[(2,7),(3,10)],[(6,1)],[(5,3)],[(5,5)],[(6,4)],[]]s =0t =6Graph as shown below(nodes 0 to 6,with edge capacities):mermaid diagram(see below)Source: 0, Sink:6Output:
Maximum flow =5Explanation:
The maximum flow from node 0 to node 6is5, as determined by the minimum cut in the network.
graph TD;
A("src: 0") -->|3| B(1)
A -->|10| E(4)
B -->|7| C(2)
B -->|10| D(3)
D -->|3| F(5)
E -->|5| F
C -->|1| G("sink: 6")
F -->|4| G
The Edmonds-Karp algorithm is a classic approach to compute the maximum flow in a network. It repeatedly finds the shortest augmenting path (in terms of number of edges) from source to sink using BFS, and augments flow along this path until no more augmenting paths exist.
classSolution {
public:int maxFlow(int n, vector<vector<pair<int,int>>>& adj, int s, int t) {
vector<vector<int>> cap(n, vector<int>(n, 0)), flow(n, vector<int>(n, 0));
for (int u =0; u < n; ++u) for (auto& [v, c] : adj[u]) cap[u][v] = c;
int ans =0;
while (true) {
vector<int> par(n, -1); queue<int> q; q.push(s);
while (!q.empty() && par[t] ==-1) {
int u = q.front(); q.pop();
for (int v =0; v < n; ++v) {
if (par[v] ==-1&& cap[u][v] - flow[u][v] >0) {
par[v] = u; q.push(v);
}
}
}
if (par[t] ==-1) break;
int f =1e9;
for (int v = t; v != s; v = par[v]) f = min(f, cap[par[v]][v] - flow[par[v]][v]);
for (int v = t; v != s; v = par[v]) {
flow[par[v]][v] += f; flow[v][par[v]] -= f;
}
ans += f;
}
return ans;
}
};
classSolution {
publicintmaxFlow(int n, List<List<int[]>> adj, int s, int t) {
int[][] cap =newint[n][n], flow =newint[n][n];
for (int u = 0; u < n; ++u)
for (int[] e : adj.get(u)) cap[u][e[0]]= e[1];
int ans = 0;
while (true) {
int[] par =newint[n]; Arrays.fill(par, -1);
Queue<Integer> q =new LinkedList<>(); q.add(s);
while (!q.isEmpty() && par[t]==-1) {
int u = q.poll();
for (int v = 0; v < n; ++v) {
if (par[v]==-1 && cap[u][v]- flow[u][v]> 0) {
par[v]= u; q.add(v);
}
}
}
if (par[t]==-1) break;
int f = Integer.MAX_VALUE;
for (int v = t; v != s; v = par[v]) f = Math.min(f, cap[par[v]][v]- flow[par[v]][v]);
for (int v = t; v != s; v = par[v]) {
flow[par[v]][v]+= f; flow[v][par[v]]-= f;
}
ans += f;
}
return ans;
}
}
classSolution:
defmax_flow(self, n: int, adj: list[list[tuple[int,int]]], s: int, t: int) -> int:
cap = [[0]*n for _ in range(n)]
flow = [[0]*n for _ in range(n)]
for u in range(n):
for v, c in adj[u]:
cap[u][v] = c
ans =0whileTrue:
par = [-1]*n
q = [s]
for u in q:
for v in range(n):
if par[v] ==-1and cap[u][v] - flow[u][v] >0:
par[v] = u
q.append(v)
if par[t] ==-1:
break f = float('inf')
v = t
while v != s:
f = min(f, cap[par[v]][v] - flow[par[v]][v])
v = par[v]
v = t
while v != s:
flow[par[v]][v] += f
flow[v][par[v]] -= f
v = par[v]
ans += f
return ans
⏰ Time complexity: O(V^2 * E), where V is the number of vertices and E is the number of edges. Each BFS takes O(E), and there can be O(V*E) augmentations.
🧺 Space complexity: O(V^2), for the capacity and flow matrices.