Logo
Published on

Network Flows - Part 3

Authors
  • avatar
    Name
    Till Heller
    Twitter

In Part 2, we defined flow networks, flows, and cuts, and proved weak duality: the value of any flow is at most the capacity of any cut. We ended with an open question — is our flow of value 55 actually optimal, and can we find a matching cut? In this part, we'll develop the tools to answer both questions at once. The key idea is the residual graph, which tells us exactly where and how we can improve a flow.

Residual Graphs

Given a flow ff in a network, some arcs might still have room for more flow, while others are completely saturated. But there's a subtlety: even on a saturated arc, we can effectively "undo" some of the flow by sending flow backwards. The residual graph captures both possibilities.

Definition 6. Given a flow network N=(D,s,t,c)N = (D, s, t, c) with D=(V,A)D = (V, A) and a flow ff, the residual capacity of an arc (u,v)A(u,v) \in A is defined as:

  • Forward residual capacity: cf(u,v)=c(u,v)f(u,v)c_f(u,v) = c(u,v) - f(u,v), representing how much more flow can be pushed along (u,v)(u,v).
  • Backward residual capacity: cf(v,u)=f(u,v)c_f(v,u) = f(u,v), representing how much flow on (u,v)(u,v) can be "cancelled" by sending flow from vv back to uu.

Definition 7. The residual graph Df=(V,Af)D_f = (V, A_f) is the directed graph on the same vertex set VV, where AfA_f contains every arc with positive residual capacity: Af={(u,v):cf(u,v)>0}.A_f = \{(u,v) : c_f(u,v) > 0\}.

The forward arcs in the residual graph tell us where we can send more flow. The backward arcs tell us where we can reroute flow that's already been assigned. This ability to "undo" flow is what makes residual graphs so powerful — it means we don't have to get the flow right on the first try.

Let's build the residual graph for our running example. Recall the flow from Part 2: f(s,a)=3f(s,a) = 3, f(s,b)=2f(s,b) = 2, f(a,b)=2f(a,b) = 2, f(a,t)=1f(a,t) = 1, f(b,t)=4f(b,t) = 4, with value f=5|f| = 5.

For each original arc, we compute the forward and backward residual capacities:

ArcCapacityFlowForward cfc_fBackward cfc_f
(s,a)(s,a)44331133 (as (a,s)(a,s))
(s,b)(s,b)22220022 (as (b,s)(b,s))
(a,b)(a,b)33221122 (as (b,a)(b,a))
(a,t)(a,t)11110011 (as (t,a)(t,a))
(b,t)(b,t)55441144 (as (t,b)(t,b))

The residual graph has arcs (omitting those with zero residual capacity): (s,a)(s,a) with capacity 11, (a,s)(a,s) with 33, (b,s)(b,s) with 22, (a,b)(a,b) with 11, (b,a)(b,a) with 22, (t,a)(t,a) with 11, (b,t)(b,t) with 11, and (t,b)(t,b) with 44.

residual-graph

Augmenting Paths

Now the key question: does the residual graph contain a path from ss to tt? If it does, we can push more flow along that path and increase the flow value. Such a path is called an augmenting path.

Definition 8. An augmenting path (with respect to a flow ff) is a directed path from ss to tt in the residual graph DfD_f.

Let's look at our residual graph. Can we find a path from ss to tt? Starting at ss, we can go to aa (residual capacity 11). From aa, we can go to bb (residual capacity 11). From bb, we can go to tt (residual capacity 11). The path sabts \to a \to b \to t is an augmenting path.

augmenting-path

How much flow can we push along this path? We're limited by the smallest residual capacity along the way — the bottleneck.

Definition 9. The bottleneck of an augmenting path PP is the minimum residual capacity along PP: Δ(P)=min(u,v)Pcf(u,v).\Delta(P) = \min_{(u,v) \in P} c_f(u,v).

For our path sabts \to a \to b \to t, the bottleneck is min(1,1,1)=1\min(1, 1, 1) = 1. We can push one additional unit of flow.

To update the flow, we increase the flow by Δ(P)\Delta(P) on each forward arc of the path and decrease it by Δ(P)\Delta(P) on each backward arc. In our case, all arcs on the path are forward arcs of the original network, so we simply add 11 to each:

f(s,a)=4,f(a,b)=3,f(b,t)=5.f'(s,a) = 4, \quad f'(a,b) = 3, \quad f'(b,t) = 5.

The arcs f(s,b)=2f(s,b) = 2 and f(a,t)=1f(a,t) = 1 remain unchanged. The new flow has value f=f(s,a)+f(s,b)=4+2=6|f'| = f'(s,a) + f'(s,b) = 4 + 2 = 6.

Let's verify that ff' is still a valid flow. At vertex aa: incoming f(s,a)=4f'(s,a) = 4, outgoing f(a,b)+f(a,t)=3+1=4f'(a,b) + f'(a,t) = 3 + 1 = 4 — conservation holds. At vertex bb: incoming f(s,b)+f(a,b)=2+3=5f'(s,b) + f'(a,b) = 2 + 3 = 5, outgoing f(b,t)=5f'(b,t) = 5 — conservation holds. All capacity constraints are satisfied too.

Can we push even more? Let's build the new residual graph for ff':

ArcCapacityFlowForward cfc_fBackward cfc_f
(s,a)(s,a)44440044 (as (a,s)(a,s))
(s,b)(s,b)22220022 (as (b,s)(b,s))
(a,b)(a,b)33330033 (as (b,a)(b,a))
(a,t)(a,t)11110011 (as (t,a)(t,a))
(b,t)(b,t)55550055 (as (t,b)(t,b))

The residual arcs are (a,s)(a,s), (b,s)(b,s), (b,a)(b,a), (t,a)(t,a), and (t,b)(t,b) — all backward arcs. Crucially, vertex ss has no outgoing arcs in the residual graph, so there is no path from ss to tt. We can't push any more flow.

The Max-Flow Min-Cut Theorem

The observation above — that a flow is maximum precisely when no augmenting path exists — is one direction of the most important theorem in network flow theory. The other direction connects this to cuts, establishing that the maximum flow value always equals the minimum cut capacity.

Theorem 1 (Max-Flow Min-Cut Theorem, Ford and Fulkerson, 1956). In a flow network N=(D,s,t,c)N = (D, s, t, c), the following three statements are equivalent:

(i) ff is a maximum flow.

(ii) There is no augmenting path with respect to ff (i.e., no ss-tt-path in the residual graph DfD_f).

(iii) There exists an ss-tt-cut (S,T)(S, T) with f=c(S,T)|f| = c(S, T).

Moreover, maxff=min(S,T)c(S,T)\max_f |f| = \min_{(S,T)} c(S,T).

Proof. We prove three implications.

(i) \Rightarrow (ii): We prove the contrapositive. Suppose there exists an augmenting path PP from ss to tt in DfD_f with bottleneck Δ(P)>0\Delta(P) > 0. Define a new flow ff' by modifying ff along PP: for each arc (u,v)(u,v) on PP, if (u,v)(u,v) is a forward arc of the original network, set f(u,v)=f(u,v)+Δ(P)f'(u,v) = f(u,v) + \Delta(P); if (u,v)(u,v) corresponds to a backward arc (i.e., (v,u)(v,u) is in the original network), set f(v,u)=f(v,u)Δ(P)f'(v,u) = f(v,u) - \Delta(P). All other arcs keep their flow. One can verify that ff' satisfies the capacity constraints (by definition of the residual capacity) and flow conservation (since on the path, each intermediate vertex gains Δ(P)\Delta(P) incoming and Δ(P)\Delta(P) outgoing). The value increases: f=f+Δ(P)>f|f'| = |f| + \Delta(P) > |f|, so ff is not maximum.

(ii) \Rightarrow (iii): Suppose there is no augmenting path. Let SS be the set of all vertices reachable from ss in the residual graph DfD_f, and let T=VST = V \setminus S. Since tt is not reachable from ss, we have sSs \in S and tTt \in T, so (S,T)(S, T) is a valid ss-tt-cut.

Now consider any arc (u,v)(u,v) in the original network with uSu \in S and vTv \in T. Since vv is not reachable from ss in DfD_f, the forward residual capacity must be zero: cf(u,v)=c(u,v)f(u,v)=0c_f(u,v) = c(u,v) - f(u,v) = 0, which means f(u,v)=c(u,v)f(u,v) = c(u,v). Similarly, for any arc (u,v)(u,v) with uTu \in T and vSv \in S, the backward residual capacity from uu to vv would make vv reachable from uu — but uTu \in T is not reachable from ss, so this isn't useful. However, the forward residual capacity of the reverse direction tells us: since vSv \in S is reachable but uTu \in T is not, we need cf(v,u)=f(u,v)=0c_f(v,u) = f(u,v) = 0.

Using the flow-cut identity from Part 2: f=(u,v)AuS,vTf(u,v)(u,v)AuT,vSf(u,v)=(u,v)AuS,vTc(u,v)0=c(S,T).|f| = \sum_{\substack{(u,v) \in A \\ u \in S, \, v \in T}} f(u,v) - \sum_{\substack{(u,v) \in A \\ u \in T, \, v \in S}} f(u,v) = \sum_{\substack{(u,v) \in A \\ u \in S, \, v \in T}} c(u,v) - 0 = c(S, T).

(iii) \Rightarrow (i): If f=c(S,T)|f| = c(S, T) for some cut (S,T)(S, T), then by weak duality (Lemma 1 from Part 2), every flow ff' satisfies fc(S,T)=f|f'| \leq c(S, T) = |f|. So ff is maximum.

The equivalence of (i), (ii), and (iii) immediately gives us the max-flow min-cut equality: maxff=min(S,T)c(S,T)\max_f |f| = \min_{(S,T)} c(S, T).

Applying the Theorem

Let's use the theorem to wrap up our running example. After augmenting, we obtained a flow ff' with value 66 and no augmenting path — condition (ii) is satisfied. By the theorem, ff' is a maximum flow.

The proof of (ii) \Rightarrow (iii) also tells us how to find the minimum cut: take SS to be the vertices reachable from ss in the residual graph. In our case, ss has no outgoing arcs in DfD_{f'}, so S={s}S = \{s\} and T={a,b,t}T = \{a, b, t\}. The cut capacity is c(s,a)+c(s,b)=4+2=6c(s,a) + c(s,b) = 4 + 2 = 6, which matches f=6|f'| = 6.

This confirms that the maximum flow is 66 and the minimum cut is ({s},{a,b,t})(\{s\}, \{a,b,t\}) with capacity 66. The bottleneck in this network is the total capacity leaving the source — the arcs out of ss are the limiting factor.

max-flow-min-cut

Integrality

There is one more property worth mentioning. In many applications, we want integer flows — you can't ship half a truck or assign half a person to a task. Fortunately, when the capacities are integers, we're guaranteed that an integer maximum flow exists.

Theorem 2 (Integrality Theorem). If all capacities in a flow network are integers, then there exists a maximum flow that is integer-valued.

This follows from the augmenting path approach: if we start with the zero flow (which is integer) and always augment along paths in the residual graph, the bottleneck Δ(P)\Delta(P) is always an integer (since it's the minimum of integer residual capacities). Each augmentation preserves integrality, and the process terminates because the flow value increases by at least 11 each time and is bounded by the finite cut capacity1.

Looking Ahead

We now have the central theorem of network flow theory and a clear strategy for finding maximum flows: repeatedly find augmenting paths and push flow along them. But several questions remain. How do we choose augmenting paths? Does the process always terminate? How fast is it? In the next part, we'll answer these questions by studying the Ford-Fulkerson method and the Edmonds-Karp algorithm, which turns the augmenting path idea into an efficient algorithm with guaranteed polynomial running time.

Footnotes

  1. The integrality theorem is essential for applications like bipartite matching, where we model the matching problem as a flow network with unit capacities. The theorem guarantees that the maximum flow corresponds to an actual matching — see Part 8 of the Introduction to Graph Theory series.