The Edmonds–Karp Rule
Ford–Fulkerson augments a flow along a residual source-to-sink path. The choice of path can affect how the process proceeds. Edmonds–Karp makes that choice precise: at every stage, it uses breadth-first search (BFS) to find a residual path with the fewest edges. The point of this tutorial is to follow that rule through a complete augmentation sequence, including the residual capacities and the final cut certificate.
For an original edge \(uv\), the residual network has a forward residual arc \(u\to v\) of capacity \(c(u,v)-f(u,v)\), when this is positive, and a reverse residual arc \(v\to u\) of capacity \(f(u,v)\), when this is positive. Sending flow on a reverse residual arc cancels flow previously sent on the corresponding original edge. If a network has original edges in both directions, their residual arcs are kept distinct; the example below has no such pair.
BFS distance layers are sets \(L_i\) of vertices at residual distance \(i\) from \(s\), where distance is the minimum number of residual arcs in a path. Thus \(L_0=\{s\}\); each later layer consists of vertices first reached from the preceding layer. A path selected by BFS follows these layers in order. Ties between shortest paths may be resolved in any way.
Why the Updates Preserve Feasibility
Proof. A shortest path has no repeated vertex: if a vertex repeated, the portion between its two occurrences could be deleted to give a shorter path. On a forward residual arc, the update increases the original-edge flow by \(\Delta\), which is permitted because the residual capacity is at least \(\Delta\). On a reverse residual arc, it decreases the corresponding original-edge flow by \(\Delta\), which is permitted because that reverse residual capacity equals the current flow and is at least \(\Delta\). Thus all edge flows remain within their capacity bounds. At each internal path vertex the full amount \(\Delta\) enters and the same amount leaves, so conservation is preserved. At \(s\), net outflow increases by \(\Delta\), and at \(t\), net inflow increases by \(\Delta\). Therefore the updated flow is feasible and has value \(|f|+\Delta\). \(\square\)
Proof. BFS starts by assigning distance \(0\) to \(s\), then processes vertices in increasing order of their assigned distance, assigning a vertex's distance when it is first reached. We show by induction on \(i\) that every vertex at distance \(i\) from \(s\) is assigned distance \(i\). This holds for \(i=0\). If it holds through \(i\), every vertex at distance \(i+1\) has a neighbor at distance \(i\), so processing that neighbor reaches it with label at most \(i+1\). It cannot be reached with a smaller label, because that would give a path of fewer than \(i+1\) edges. Hence its assigned distance is \(i+1\). If \(t\) is reachable, following the predecessor links used to assign its label gives a path of that minimum length. If it is not reached, no residual path to \(t\) exists: the first unreached vertex on any proposed path would have been reached from its preceding vertex. \(\square\)
Tracing the Augmentations
Worked Example: The First Shortest Augmenting Path
Let the directed network have \(V=\{s,a,b,c,d,t\}\) and capacity-labelled edge set \(E=\{s\to a:16,\ s\to b:13,\ a\to b:10,\ a\to c:12,\ c\to b:9,\ b\to d:14,\ d\to c:7,\ c\to t:20,\ d\to t:4\}\). All initial flows are zero, so each forward residual capacity initially equals its listed capacity and there are no positive reverse residual capacities.
Run BFS with \(a\) processed before \(b\) when both are available. The layers are \(L_0=\{s\}\), \(L_1=\{a,b\}\), \(L_2=\{c,d\}\), and \(L_3=\{t\}\). In particular, \(s\to a\to c\to t\) and \(s\to b\to d\to t\) both have length \(3\). Processing \(c\) before \(d\) discovers \(t\) by the first of these, so choose \(s\to a\to c\to t\).
The residual capacities along this path are \(16,12,20\), so the bottleneck is \(\Delta=\min(16,12,20)=12\). The update sends \(12\) units on each path edge. The forward residual capacities become \(s\to a:16-12=4\), \(a\to c:12-12=0\), and \(c\to t:20-12=8\). The reverse residual capacities become \(a\to s:12\), \(c\to a:12\), and \(t\to c:12\). The flow value is \(12\).
Check: \(a\) receives \(12\) and sends \(12\); \(c\) receives \(12\) and sends \(12\). The source sends \(12\), agreeing with the flow value. No capacity is exceeded.
Worked Example: The Second Shortest Augmenting Path
Use the same network \(V=\{s,a,b,c,d,t\}\) and capacity-labelled edge set \(E=\{s\to a:16,\ s\to b:13,\ a\to b:10,\ a\to c:12,\ c\to b:9,\ b\to d:14,\ d\to c:7,\ c\to t:20,\ d\to t:4\}\), starting from the residual network just obtained.
BFS now gives \(L_0=\{s\}\), \(L_1=\{a,b\}\), \(L_2=\{d\}\), and \(L_3=\{c,t\}\). From \(a\), the arc \(a\to b\) reaches a vertex already in \(L_1\), and \(a\to c\) has residual capacity \(0\). From \(b\), the positive arc \(b\to d\) reaches \(d\). From \(d\), both \(d\to c\) and \(d\to t\) have positive residual capacity, so \(c\) and \(t\) enter \(L_3\). A shortest path is \(s\to b\to d\to t\).
Its residual capacities are \(13,14,4\), so \(\Delta=\min(13,14,4)=4\). The updated forward residual capacities are \(s\to b:13-4=9\), \(b\to d:14-4=10\), and \(d\to t:4-4=0\). The new reverse residual capacities are \(b\to s:4\), \(d\to b:4\), and \(t\to d:4\). The flow value is \(12+4=16\).
Check: \(b\) receives \(4\) and sends \(4\); \(d\) receives \(4\) and sends \(4\). Together with the first path, the flow on \(s\to a\) is \(12\) and on \(s\to b\) is \(4\), so the source outflow is \(12+4=16\).
Worked Example: The Third Path and the Final Residual Search
Again use \(V=\{s,a,b,c,d,t\}\) and \(E=\{s\to a:16,\ s\to b:13,\ a\to b:10,\ a\to c:12,\ c\to b:9,\ b\to d:14,\ d\to c:7,\ c\to t:20,\ d\to t:4\}\), now with both previous augmentations applied.
The BFS layers are \(L_0=\{s\}\), \(L_1=\{a,b\}\), \(L_2=\{d\}\), \(L_3=\{c\}\), and \(L_4=\{t\}\). From \(s\), both \(a\) and \(b\) are reached. The residual arc \(a\to b\) adds no new vertex; \(b\to d\) reaches \(d\). Then \(d\to c\) reaches \(c\), and \(c\to t\) reaches \(t\). The selected shortest path is \(s\to b\to d\to c\to t\).
The residual capacities on this path are \(9,10,7,8\), so \(\Delta=\min(9,10,7,8)=7\). The forward residual capacities become \(s\to b:9-7=2\), \(b\to d:10-7=3\), \(d\to c:7-7=0\), and \(c\to t:8-7=1\). The reverse residual capacities on the path become \(b\to s:4+7=11\), \(d\to b:4+7=11\), \(c\to d:7\), and \(t\to c:12+7=19\). The value is \(16+7=23\).
Run BFS once more. It reaches \(a,b\) in \(L_1\), then \(d\) in \(L_2\) using \(b\to d\), but no new vertex from \(d\): \(d\to c\) and \(d\to t\) have residual capacity \(0\), while \(d\to b\) leads to a vertex already reached. Thus \(t\) is unreachable. The set of vertices reachable from \(s\) is \(S=\{s,a,b,d\}\).
Check: The final original-edge flows are \(f(s,a)=12,\ f(s,b)=11,\ f(a,b)=0,\ f(a,c)=12,\ f(c,b)=0,\ f(b,d)=11,\ f(d,c)=7,\ f(c,t)=19,\ f(d,t)=4\). At \(a\), inflow and outflow are both \(12\); at \(b\), both are \(11\); at \(d\), both are \(11\); at \(c\), inflow is \(12+7=19\) and outflow is \(19\). The source outflow is \(12+11=23\).
Why the Final Cut Certifies the Answer
Proof. Since there is no residual \(s\)-\(t\) path, \(s\in S\) and \(t\notin S\). Every original edge from \(S\) to \(V\setminus S\) is saturated; otherwise its forward residual arc would reach a vertex outside \(S\). Every original edge from \(V\setminus S\) into \(S\) carries zero flow; otherwise its reverse residual arc would go from \(S\) to \(V\setminus S\), again reaching a vertex outside \(S\). Sum net outflow over all vertices in \(S\). Internal edges cancel, and flow conservation cancels the contributions of vertices other than \(s\), so the sum is the flow value. The crossing edges from \(S\) to \(V\setminus S\) contribute their full capacities, and edges in the opposite direction contribute zero. Hence the flow value equals the capacity of this cut. For any feasible flow and any cut separating \(s\) from \(t\), the same cancellation shows that its value is at most the cut capacity: each outward edge carries at most its capacity and each inward edge has nonnegative flow. Therefore no flow can exceed the current flow's value, proving maximality. \(\square\)
For the example, the edges leaving \(S=\{s,a,b,d\}\) are \(a\to c\), \(d\to c\), and \(d\to t\). Their capacities are \(12,7,4\), so the cut capacity is \(12+7+4=23\), equal to the flow value. This independently verifies the final answer: the flow is maximum and this cut is minimum.
Common Pitfall: Updating by the Wrong Amount
A path augmentation does not generally send one unit. On the third path here, the bottleneck is \(7\), so the full augmentation amount enters and leaves each internal vertex. For instance, at \(d\), \(7\) units enter on \(b\to d\) and \(7\) leave on \(d\to c\); conservation is preserved. A wrong update that subtracts only \(1\) from \(c\to t\) would give \(8-1=7\), but the correct residual capacity is \(8-7=1\). The bottleneck determines every forward subtraction and reverse addition on the path.
Edmonds–Karp is therefore more than a choice of a convenient path: BFS fixes the path length at each step, and the residual updates determine the next set of layers. Keeping those layers, bottlenecks, and reverse capacities explicit makes the sequence auditable. The final reachable set then turns the computation into a certificate rather than relying on the appearance of the flow alone.
Check Your Understanding
Use the network and residual updates above to answer these questions.
- After the first augmentation, why is \(s\to b\to d\to t\) still a shortest residual path?
- After the second augmentation, list the BFS layers that lead to \(s\to b\to d\to c\to t\).
- After the third augmentation, what are the residual capacities of \(b\to d\), \(d\to c\), and \(c\to t\)?
- For the final reachable set \(S\), which original edges cross from \(S\) to its complement, and what is their total capacity?
- Explain why a feasible flow whose value equals the capacity of a cut must be maximum.