Maximum flow (Edmonds–Karp)
While the residual network has a path from the source to the last node, find the shortest one with BFS and push flow along it.
Every edge has a capacity. We want to send as much flow as possible from the source (the chosen node) to the sink (the last node), never exceeding an edge's capacity, with everything that enters a node also leaving it.
Read the full explanation ↓- Time:
O(V · E²) - Space:
O(V + E) - CLRS, section 24.2
- Grimaldi, chapter 13
The well-known six-node network from S to T; the maximum flow is 23.
from collections import dequeINF = float("inf")def edmonds_karp(graph, s):t = list(graph)[-1] # the last node is the sinkcap = {u: {} for u in graph}for u in graph:for v, w in graph[u]:cap[u][v] = cap[u].get(v, 0) + wcap[v].setdefault(u, 0)total = 0while True:parent = {v: None for v in graph}seen = {s}queue = deque([s])while queue and t not in seen:u = queue.popleft()for v in cap[u]:if cap[u][v] == 0 or v in seen:continueseen.add(v)parent[v] = uqueue.append(v)if t not in seen:return totalbottleneck = INFv = twhile v != s:bottleneck = min(bottleneck, cap[parent[v]][v])v = parent[v]v = twhile v != s:u = parent[v]cap[u][v] = cap[u][v] - bottleneckcap[v][u] = cap[v][u] + bottleneckv = utotal = total + bottleneck
Start
- Current node
(u) - Search tree (from parent)
- Edge being checked
Queue queue
empty
Local variables
Orange = changed in this step
graph dict
- 'S': [('A', 16), ('B', 13)]
- 'A': [('C', 12)]
- 'B': [('A', 4), ('D', 14)]
- 'C': [('B', 9), ('T', 20)]
- 'D': [('C', 7), ('T', 4)]
- 'T': []
Call stack
- edmonds_karp()line 6
How the work grows with input size
Average of 5 random graphs per n (fixed seeds). Hollow marker = the input on screen.
- take
- push
- current input (n=6)
Show as a table
| n | take | push |
|---|---|---|
| 4 | 7.8 | 5.2 |
| 8 | 20.4 | 8.8 |
| 12 | 28.2 | 11.6 |
Explanation
The idea
Every edge has a capacity. We want to send as much flow as possible from the source (the chosen node) to the sink (the last node), never exceeding an edge's capacity, with everything that enters a node also leaving it.
The Ford–Fulkerson method
- Find a path from the source to the sink in the residual network (the capacity that is still free): an augmenting path.
- Send the smallest capacity on the path (the bottleneck).
- For every edge
u → vthat got flow, give the reverse edgev → uthe same amount of capacity, so the flow can later be taken back.
Repeat while an augmenting path exists. The max-flow min-cut theorem says the final answer is optimal.
Why BFS?
Edmonds and Karp showed that if we always take the shortest path (with BFS), there are at most O(V·E) rounds:
O(V·E²) in total, no matter how large the capacities are.
What to watch in the trace
- The coloured edges are the current BFS tree; the augmenting path lies on it.
- The
capdictionary in the memory panel holds the residual capacities; "taking flow back" shows a reverse edge in use.