Edmonds-Karp, Capacity Scaling, Push-Relabel
What This Concept Is
Ford-Fulkerson is a method, not an algorithm - it leaves open how to pick an augmenting path. Three standard choices give polynomial-time algorithms:
- Edmonds-Karp. Always pick a shortest augmenting path (fewest edges, not smallest weight) using BFS on the residual graph. Runs in
O(|V| |E|^2). - Capacity scaling. Keep a threshold
Delta, starting at the largest power of2at most the max capacity. Repeatedly find augmenting paths whose bottleneck residual capacity is at leastDelta, then halveDelta. Runs inO(|E|^2 log U)whereUis the max capacity. - Push-relabel (Goldberg-Tarjan). Maintain a preflow and vertex heights; push excess toward the sink along "downhill" admissible edges; relabel a vertex when no admissible out-edge exists. The generic version runs in
O(|V|^2 |E|); the highest-label variant inO(|V|^2 sqrt(|E|)); the FIFO variant inO(|V|^3).
Dinic's algorithm (not in this module's core but worth naming) uses level graphs and blocking flows for O(|V|^2 |E|), and O(|E| sqrt(|V|)) on unit-capacity graphs and on bipartite matching - often the fastest practical algorithm when combined with link-cut trees.
The headline intuition: Ford-Fulkerson's correctness does not depend on path choice, but its running time does. Changing from DFS to BFS converts an exponential-in-value algorithm into a polynomial-in-structure one.
Why It Matters Here
Moving from "Ford-Fulkerson method" to "a specific polynomial-time algorithm" is the practical transition from "flows exist in theory" to "I can use flows in a system."
- Edmonds-Karp is what most introductory implementations actually are, even if they are called "Ford-Fulkerson." If you choose BFS for the augmenting path, you have Edmonds-Karp.
- Capacity scaling is a cheap polynomial-time upgrade for graphs with huge but integer capacities; it pushes at least
Deltaunits per augmentation, keeping iteration count bounded. - Push-relabel is the basis of the fastest practical max-flow libraries, including the ones used inside modern graph-cut segmentation tools (Boykov-Kolmogorov variant) and commercial network-flow solvers.
The three algorithms also illustrate distinct algorithmic paradigms: augmenting paths (Edmonds-Karp), parameterized search (capacity scaling), and preflow manipulation (push-relabel).
Concrete Example
On the same network from the Ford-Fulkerson page:
Edmonds-Karp (BFS) trace:
| iter | augmenting path (BFS) | length | bottleneck | total flow |
|---|---|---|---|---|
| 1 | s-a-t | 2 | 4 | 4 |
| 2 | s-b-c-t | 3 | 9 | 13 |
| 3 | s-a-c-t | 3 | 1 | 14 |
| 4 | no s-t path in residual | - | - | terminate |
Max flow = 14. Notice BFS prevents the pathological long augmenting paths that adversarial graphs can exploit against arbitrary-path Ford-Fulkerson - each edge can be the bottleneck on at most |V|/2 augmentations because BFS path lengths are nondecreasing.
Capacity scaling on an adversarial graph:
s -(10^9)-> a, s -(10^9)-> b
a -(1)-> b
a -(10^9)-> t, b -(10^9)-> t
With Delta = 2^30, the algorithm ignores the (a,b) edge entirely and finishes in two augmentations. Plain Ford-Fulkerson with DFS that alternately chooses s-a-b-t and s-b-a-t would take 2 * 10^9 iterations.
Common Confusion / Misconceptions
- "Edmonds-Karp is Ford-Fulkerson with BFS." Yes, but the specific guarantee is that the augmenting-path length is nondecreasing across iterations, and each edge can be the bottleneck on at most
O(|V|)augmentations. These two facts together yieldO(|V| |E|^2); it is a nontrivial proof, not a restatement of Ford-Fulkerson. - "Push-relabel uses augmenting paths." It does not. It manipulates a preflow (which may temporarily violate conservation) and gradually pushes excess toward the sink using vertex heights; the structure is local rather than end-to-end.
- "Capacity scaling is just Edmonds-Karp with integer math." No - it is a different control strategy: find only "big" augmenting paths, halve the threshold, repeat. The scaling trick is common in combinatorial optimization.
- "Dinic is only for unit capacities." Dinic works on arbitrary capacities in
O(|V|^2 |E|); theO(|E| sqrt(|V|))bound is specific to unit-capacity and bipartite graphs.
How To Use It
Default choice for this module: implement Ford-Fulkerson with BFS (Edmonds-Karp). It is clean, has a polynomial bound, and matches what interviews and systems questions expect.
If you need more performance, escalate in this order:
- Edmonds-Karp with fast adjacency-list traversal and reverse-pointer residuals.
- Capacity scaling on top of Edmonds-Karp when max capacity
Uis huge (for example, bandwidths in bytes). - Dinic's algorithm, especially for bipartite matching (see Hopcroft-Karp) and unit-capacity networks.
- Push-relabel from an existing high-quality library (OR-Tools, Boost.Graph) when the graph is dense or push-relabel-friendly.
Skeleton for Edmonds-Karp:
while BFS from s in residual graph reaches t:
reconstruct path via parent[]
delta := min residual capacity along path
push delta along path (decrement forward, increment reverse)
total := total + delta
return total
Transfer / Where This Shows Up Later
- S3 (systems). Bandwidth shaping (
tc), QoS, data-center fabric allocation - all use flow-based algorithms under the hood. - S4 (compilers). Register allocation via max-flow/min-cut formulations; instruction scheduling with resource constraints.
- S5 (OS). I/O scheduling, process migration bandwidth planning; the Boykov-Kolmogorov max-flow appears in computer-vision kernels.
- S6 (databases). Query optimization: push-relabel-like ideas for join ordering under memory bounds; transaction flow in lock managers.
- S7 (DDD). Bounded-context capacity analysis, integration-bottleneck identification via min-cuts.
- S8 (distributed). Traffic engineering in large networks, MPLS path computation, multi-commodity flow approximations.
Back-link to concept 17 (Ford-Fulkerson method), forward to concept 19 (max-flow/min-cut duality) and concept 20 (bipartite matching via flow).
Check Yourself
- Why does picking a shortest augmenting path give polynomial time where arbitrary paths do not?
- What does capacity scaling buy over plain Edmonds-Karp?
- What is a "preflow" and how does it differ from a flow?
- Why is push-relabel's running time expressed in
|V|^2 |E|rather than something in|E|alone? - On a unit-capacity network, why does Dinic's run in
O(|E| sqrt(|V|))? - Show an adversarial graph where Edmonds-Karp beats DFS-Ford-Fulkerson by more than a factor of 100.
Mini Drill or Application
Compare Ford-Fulkerson (DFS-chosen augmenting paths) and Edmonds-Karp (BFS) on the adversarial graph:
s -(1000)-> a, s -(1000)-> b
a -(1)-> b
a -(1000)-> t, b -(1000)-> t
Construct a sequence of augmenting paths for Ford-Fulkerson that forces 2000 iterations, and show that Edmonds-Karp terminates in at most 3 iterations.
Implementation drills.
- Implement Edmonds-Karp end-to-end with residual edges. Test on a 10-vertex network.
- Add capacity scaling on top; verify on the adversarial graph above - iteration count should drop by orders of magnitude.
- Write a simple push-relabel (FIFO order); verify same max-flow values as Edmonds-Karp on the same test set.
- Benchmark the three on random networks of 100/500/1000 vertices; produce a short comparison table.
- Plug your Edmonds-Karp into a project-selection instance: given 10 projects with revenues and prerequisite costs, compute the maximum-profit subset via max-flow/min-cut.
Read This Only If Stuck
- CLRS 24.2: Ford-Fulkerson Method (Part 2)
- CLRS 24.2: Ford-Fulkerson Method (Part 3)
- CLRS 24.2: Ford-Fulkerson Method (Part 4)
- CLRS 24.2: Ford-Fulkerson Method (Part 5)
- ADM 6.5: Network Flows and Bipartite Matching
- Sedgewick: Flow Networks
- Competitive Programming: Network Flow
- Competitive Programming: Max Flow Applications
- cp-algorithms: Edmonds-Karp
- cp-algorithms: Dinic's Algorithm