A flow network is a directed graph where each edge has a capacity (the maximum amount of flow it can carry). The goal is to find the maximum amount of flow that can be sent from a source vertex (s) to a sink vertex (t) while respecting all capacity constraints.
0 ≤ flow ≤ capacity.The Ford-Fulkerson method is a greedy iterative algorithm. It repeatedly finds an augmenting path from s to t in the residual graph and pushes flow along that path. The process repeats until no more augmenting paths exist.
The residual graph Gf shows the remaining capacity on each edge after some flow has been sent. For each original edge (u, v) with capacity c and flow f, the residual graph contains:
c - f.f (allowing flow to be undone).def ford_fulkerson(graph, source, sink):
n = len(graph)
# Residual graph: res[u][v] = remaining capacity
res = [row[:] for row in graph]
max_flow = 0
def bfs(s, t, parent):
visited = [False] * n
queue = [s]
visited[s] = True
while queue:
u = queue.pop(0)
for v in range(n):
if not visited[v] and res[u][v] > 0:
parent[v] = u
visited[v] = True
queue.append(v)
if v == t:
return True
return False
parent = [-1] * n
while bfs(source, sink, parent):
# Find the bottleneck capacity along the augmenting path
bottleneck = float('inf')
v = sink
while v != source:
u = parent[v]
bottleneck = min(bottleneck, res[u][v])
v = u
# Update residual capacities
v = sink
while v != source:
u = parent[v]
res[u][v] -= bottleneck
res[v][u] += bottleneck
v = u
max_flow += bottleneck
return max_flow
Edmonds-Karp is a specific implementation of Ford-Fulkerson that uses BFS to find the shortest augmenting path (in terms of number of edges). This guarantees O(V * E²) time complexity, whereas a naive DFS-based Ford-Fulkerson can be exponential.
O(V * E). Each BFS costs O(E), yielding O(V * E²) overall.
One of the most important results in network flow theory:
The value of the maximum flow from s to t equals the capacity of the minimum s-t cut.
An s-t cut is a partition of vertices into two sets S and T (with s in S and t in T such that the sum of capacities of edges from S to T is minimized). The minimum cut is the bottleneck of the network.
# Bipartite matching via max flow
def max_bipartite_matching(left, right, edges):
# Build flow network:
# source = 0, left = 1..|left|, right = |left|+1..|left|+|right|, sink = last
n = 2 + len(left) + len(right)
graph = [[0]*n for _ in range(n)]
source, sink = 0, n - 1
for i in range(len(left)):
graph[source][1 + i] = 1
for i in range(len(right)):
graph[1 + len(left) + i][sink] = 1
for u, v in edges:
graph[1 + u][1 + len(left) + v] = 1
return ford_fulkerson(graph, source, sink)
| Algorithm | Time Complexity | Notes |
|---|---|---|
| Ford-Fulkerson (DFS) | O(E * |f|) | Depends on max flow value; can be slow |
| Edmonds-Karp (BFS) | O(V * E²) | Polynomial; guarantees termination |
| Dinic's | O(V² * E) | Faster for unit-capacity graphs; O(E * sqrt(V)) for bipartite matching |
Given a flow network with 5 nodes (source=0, sink=4) and the following capacities:
graph = [
[0, 16, 13, 0, 0],
[0, 0, 10, 12, 0],
[0, 4, 0, 0, 14],
[0, 0, 9, 0, 20],
[0, 0, 0, 0, 0]
]
Implement Edmonds-Karp to compute the max flow. Then find the min-cut edges by running BFS on the residual graph.