Edmonds-Karp
Ford-Fulkerson is a method, not an algorithm — it just says "find augmenting paths until none exist" without specifying how to find them. With DFS you might get lucky, or you might spin forever on bad paths.
Edmonds-Karp makes one simple, powerful change: use BFS to always find the shortest augmenting path (fewest edges). That's it. One line different. But it gives you a polynomial worst-case guarantee no matter what the capacities are.
Why DFS Can Be Terrible
Picture two paths from s to t: one through a narrow bridge with capacity 1, another around it with capacity 1,000,000. With DFS, you might alternate between these two paths forever, sending just 1 unit each time. After 2,000,000 iterations, you've finished what BFS would have done in two steps.
With irrational capacities, DFS-based Ford-Fulkerson can even fail to terminate — oscillating without converging to the correct answer.
BFS Saves the Day: The Monotonicity Argument
When you always augment along the shortest path (by number of edges), augmenting path lengths can only stay the same or increase — they never decrease. This monotonicity is the key to the polynomial bound.
Here's why it matters: once a path of length L is used repeatedly, eventually its bottleneck edge gets saturated and removed. That edge might come back via a backward edge later — but only as part of a longer path. Since path lengths are bounded by V, the total number of augmentations is bounded.
The \(O(VE^2)\) Proof Sketch
Each edge can become a bottleneck at most \(O(V)\) times before the shortest path length increases past it. There are E edges. So: \(O(V)\) bottleneck events per edge × E edges = \(O(VE)\) total augmentations. Each augmentation runs one BFS costing \(O(E)\). Total: \(O(VE)\) × \(O(E)\) = \(O(VE^2)\).
This is independent of the maximum flow value — a true polynomial bound in graph size, not flow magnitude.
Implementation
The only difference from a basic Ford-Fulkerson is using a queue (BFS) instead of a stack/recursion (DFS) to find augmenting paths. Residual graph management is identical: for each edge (u→v), store both forward capacity and backward capacity as a pair.