Ford-Fulkerson Method

Picture a network of pipes carrying oil from a single source refinery to a single destination port. Each pipe has a maximum capacity. How much oil can flow from source to destination per unit time? Along which pipes should it travel? This is the maximum flow problem. It shows up far beyond literal pipelines. Routing internet packets, scheduling airline crews, matching applicants to jobs, and segmenting images in computer vision all reduce to finding a maximum flow. Each of these problems maps onto a suitably constructed graph. The Ford-Fulkerson method, introduced in 1956, gives the first general algorithmic answer. It repeatedly finds a path along which more flow can still be pushed. It pushes as much as possible along that path. This repeats until no such path exists. The elegance of the method lies in a clever bookkeeping device called the residual graph. This device lets the algorithm "undo" earlier bad routing decisions by pushing flow backward. This single idea — augmenting paths in a residual graph — is the ancestor of nearly every modern max-flow algorithm. Ford-Fulkerson is officially a method rather than a fully specified algorithm. This is because it does not say which augmenting path to pick. Chosen carelessly, it can be shockingly slow. It can even fail to terminate on irrational capacities. Chosen wisely — via breadth-first search — it becomes the Edmonds-Karp refinement. This gives a clean polynomial-time algorithm with a satisfying complexity proof. This article develops the method in full. It covers the residual graph construction and the augmenting-path loop. It explains why the method terminates and returns a correct answer. It also covers the specific pathologies that arise from bad path choices. Finally, it shows how BFS tames them into a provably efficient algorithm. Understanding Ford-Fulkerson is also the cleanest route into one of the most beautiful theorems in combinatorial optimization. That theorem is the Max-Flow Min-Cut Theorem. It also directly powers algorithms for Bipartite Matching via Augmenting Paths. Everything here builds on Network Flow Fundamentals. It uses Breadth-First Search as a core subroutine.

Key takeaways
  • Max flow is computed by repeatedly finding an augmenting path from source to sink in a residual graph and pushing flow along it.
  • The residual graph encodes both remaining forward capacity and the ability to cancel previously sent flow via reverse edges.
  • The method terminates when no augmenting path exists; at that point the current flow is provably maximum.
  • With arbitrary path selection and irrational capacities, Ford-Fulkerson can fail to terminate; with integer capacities it terminates but can take pseudo-polynomial time.
  • Edmonds-Karp picks the shortest augmenting path (via BFS), guaranteeing termination in O(VE2)O(VE^2) time regardless of capacity values.
  • The final residual graph directly exposes a minimum cut, connecting this algorithm to the Max-Flow Min-Cut Theorem.
The core insight

Maximum flow is found by repeatedly augmenting along paths in a residual graph until none remain — and how you choose those paths determines whether the algorithm is fast, slow, or infinite.

The idea

A flow network is a directed graph G=(V,E)G = (V, E) with a source ss, a sink tt, and a capacity c(u,v)≥0c(u,v) \ge 0 on every edge. A flow is a function f(u,v)f(u,v) satisfying capacity constraints 0≤f(u,v)≤c(u,v)0 \le f(u,v) \le c(u,v) and flow conservation at every vertex other than ss and tt: total flow in equals total flow out. The value of a flow is the net flow leaving ss, and the maximum flow problem asks for a flow of maximum value. The central construct is the residual graph GfG_f, which depends on the current flow ff. For every edge (u,v)(u,v) with capacity c(u,v)c(u,v) and current flow f(u,v)f(u,v), the residual graph contains:

  • a forward residual edge (u,v)(u,v) with residual capacity cf(u,v)=c(u,v)−f(u,v)c_f(u,v) = c(u,v) - f(u,v), present whenever this is positive — it represents unused capacity;
  • a backward residual edge (v,u)(v,u) with residual capacity cf(v,u)=f(u,v)c_f(v,u) = f(u,v), present whenever this is positive — it represents the ability to cancel flow already sent from uu to vv.

An augmenting path is any directed path from ss to tt in GfG_f using only edges of positive residual capacity. Its bottleneck capacity is the minimum residual capacity along the path. Pushing flow equal to the bottleneck along every edge of the path strictly increases the flow value while preserving feasibility — forward edges get more flow, backward edges get flow subtracted (i.e., some previously sent flow is rerouted elsewhere). This is the mechanism that lets Ford-Fulkerson escape locally greedy but globally suboptimal routing decisions made early on.

How it works

The method is a loop: build the residual graph, search it for any ss-tt path, augment along it, and repeat. It terminates precisely when the residual graph has no path from ss to tt — equivalently, when tt is unreachable from ss using only positive-residual edges. ``` FORD-FULKERSON(G, s, t): for each edge (u, v) in G.E: f(u, v) = 0 f(v, u) = 0 // symmetric bookkeeping, or track only forward while there exists a path p from s to t in the residual graph G_f: c_f(p) = min { c_f(u, v) : (u, v) is an edge on p } // bottleneck for each edge (u, v) on p: if (u, v) is a "forward" original edge: f(u, v) = f(u, v) + c_f(p) else: // (u, v) is a reverse of original edge (v, u) f(v, u) = f(v, u) - c_f(p) // residual capacities are implicitly updated: // c_f(u,v) = c(u,v) - f(u,v), c_f(v,u) = f(u,v) return f ``` ``` EDMONDS-KARP(G, s, t): for each edge (u, v) in G.E: f(u, v) = 0 loop: // BFS in the residual graph, restricted to positive-capacity edges find shortest path p from s to t in G_f using BFS if no such path exists: return f c_f(p) = min { c_f(u, v) : (u, v) on p } for each edge (u, v) on p: augment f along (u, v) by c_f(p) // updates both the forward residual and the paired backward residual ``` Two design choices make this precise and implementable: 1. Residual capacity bookkeeping is usually done with a paired-edge representation: every original edge (u,v)(u,v) with capacity cc is stored alongside a reverse edge (v,u)(v,u) with capacity 00 initialized. Sending δ\delta units of flow along (u,v)(u,v) decreases the residual capacity of (u,v)(u,v) by δ\delta and increases the residual capacity of (v,u)(v,u) by δ\delta, automatically implementing cancellation. 2. Path search can be any graph search — DFS, BFS, or something smarter. Generic Ford-Fulkerson leaves this unspecified; Edmonds-Karp nails it down to BFS, which finds a shortest (fewest-edges) augmenting path each iteration.

Figure
Residual graph after one augmentation: forward edges shrink, reverse edges appear
Original network (capacities) s a b t 10 10 4 10 6 Residual graph after augmenting 4 (s→a→b→t) s a b t 6 fwd 4 back 10 fwd 0 (sat.) 10 fwd 2 fwd 4 back Edge a→t is saturated (0 residual): no longer usable. Dashed red = reverse residual edges created by the flow just sent.

Complexity & correctness

Correctness (why the final flow is maximum). The proof rests on the max-flow min-cut correspondence. Define a cut (S,T)(S, T) as a partition of VV with s∈Ss \in S, t∈Tt \in T; its capacity is the sum of capacities of edges from SS to TT. For any flow ff and any cut, the flow value equals the net flow across the cut, which is at most the cut's capacity. So max flow ≤\le min cut always. When Ford-Fulkerson terminates, there is no augmenting path in GfG_f, meaning tt is unreachable from ss in the residual graph. Let SS be the set of vertices reachable from ss in GfG_f, and T=V∖ST = V \setminus S. Since no residual edge crosses from SS to TT:

  • every original edge from SS to TT must be fully saturated (f(u,v)=c(u,v)f(u,v) = c(u,v)), otherwise a positive-residual forward edge would exist and vv would be reachable;
  • every original edge from TT to SS must carry zero flow (f(v,u)=0f(v,u) = 0), otherwise a positive-residual backward edge would put vv in SS.

The flow value therefore equals exactly the capacity of cut (S,T)(S,T). Combined with the general inequality (flow value ≤\le any cut capacity), this flow value is the maximum possible, and (S,T)(S,T) is a minimum cut. This is the constructive core of the Max-Flow Min-Cut Theorem: Ford-Fulkerson doesn't just compute max flow, it exhibits a matching min cut as a certificate of optimality.

Termination and pseudo-polynomial time. Each augmentation strictly increases the flow value by at least 1 (assuming integer capacities), and the flow value is bounded above by the finite min cut capacity, so the loop must terminate. If f∗f^* is the max flow value, at most f∗f^* augmentations occur, each requiring O(E)O(E) work to find a path (DFS/BFS) and O(V)O(V) to augment, giving O(E⋅f∗)O(E \cdot f^*) total time. This is pseudo-polynomial: it depends on the numeric magnitude of capacities, not just the graph size, and can be exponential in the input's bit-length if capacities are large and paths are chosen adversarially.

Non-termination with irrational capacities. If capacities are irrational and augmenting paths are chosen adversarially, Ford-Fulkerson can run forever, converging to a value strictly less than the true max flow — a classical counterexample (due to Ford and Fulkerson themselves, later elaborated) uses the golden ratio to construct an infinite non-terminating sequence of shrinking augmentations. This is why the method, left unspecified, is not an algorithm in the strict sense.

Edmonds-Karp: BFS fixes everything. Edmonds-Karp always augments along a shortest ss-tt path in the residual graph (fewest edges, found by BFS, each edge weight treated as 1). Two facts drive the complexity proof: 1. The shortest-path distance from ss to any vertex vv in the residual graph is monotonically non-decreasing over the course of the algorithm. Intuitively, augmenting can only remove edges (saturating them) and add reverse edges that point "backward," which cannot shorten future forward paths. 2. Each edge can be the bottleneck (the unique saturating edge) of an augmenting path at most O(V)O(V) times. When an edge (u,v)(u,v) is the bottleneck, it disappears from the residual graph; for it to reappear, flow must be pushed back along (v,u)(v,u), which requires vv to precede uu on a later shortest path — and the distance argument shows the shortest-path length to uu must have strictly increased by at least 2 between consecutive times (u,v)(u,v) is a bottleneck. Since shortest-path length is bounded by V−1V - 1, this can happen at most O(V)O(V) times per edge. With O(E)O(E) edges each saturating O(V)O(V) times, there are O(VE)O(VE) augmentations total. Each augmentation costs O(E)O(E) for the BFS. Total time:

O(VE)×O(E)=O(VE2).O(VE) \times O(E) = O(VE^2).

This bound is independent of capacity values — a genuinely polynomial algorithm, unlike the generic method.

Space. Both variants use O(V+E)O(V + E) space for the graph and residual capacities, plus O(V)O(V) for BFS/DFS bookkeeping — no more than the input itself requires.

Honest tradeoffs. Edmonds-Karp's O(VE2)O(VE^2) is often outperformed in practice by other refinements — Dinic's algorithm achieves O(V2E)O(V^2E) using blocking flows and level graphs, and push-relabel variants achieve even better bounds on dense graphs — but Edmonds-Karp remains the simplest provably polynomial instantiation of the Ford-Fulkerson idea and the natural stepping stone toward those algorithms.

Worked example

Consider this small network (capacities shown), computing max flow from ss to tt:

EdgeCapacity
s → a10
s → b10
a → b2
a → t4
b → t9

Run Edmonds-Karp (BFS picks shortest augmenting paths):

IterationBFS path foundBottleneckFlow value afterNotes
1s → a → tmin(10, 4) = 44a→t now saturated
2s → b → tmin(10, 9) = 913b→t now saturated
3s → a → b → tneed residual on b→t: none forward, but check residual of a→b, and reverse on b→t?—b→t saturated forward; reverse edge t→b has capacity 9 but doesn't help toward t
3′s → a → b → t is invalid (b→t forward is 0); try s → a → ...no path with positive residual reaches t—search terminates

Let's be precise about iteration 3. After iterations 1–2, residual capacities are:

  • cf(s,a)=10−4=6c_f(s,a) = 10 - 4 = 6, cf(a,s)=4c_f(a,s) = 4
  • cf(s,b)=10−9=1c_f(s,b) = 10 - 9 = 1, cf(b,s)=9c_f(b,s) = 9
  • cf(a,b)=2c_f(a,b) = 2 (untouched), cf(b,a)=0c_f(b,a) = 0
  • cf(a,t)=4−4=0c_f(a,t) = 4 - 4 = 0, cf(t,a)=4c_f(t,a) = 4
  • cf(b,t)=9−9=0c_f(b,t) = 9 - 9 = 0, cf(t,b)=9c_f(t,b) = 9

BFS from ss: reachable via s→as \to a (residual 6) and s→bs \to b (residual 1). From aa, can reach bb (residual 2) — but not tt (residual 0). From bb, can reach... nothing new toward tt (residual 0). So tt is unreachable. The algorithm terminates with flow value 4+9=134 + 9 = 13. Verify optimality via the cut exposed by the final BFS reachable set S={s,a,b}S = \{s, a, b\}, T={t}T = \{t\}. Capacity of this cut is c(a,t)+c(b,t)=4+9=13c(a,t) + c(b,t) = 4 + 9 = 13, exactly matching the flow value — confirming, by the max-flow min-cut argument, that 13 is indeed optimal, and no cleverer path selection could have done better. Compare with what a badly chosen DFS-based generic Ford-Fulkerson might do on a network with capacities 1000, 1000, 1 in a specific gadget (the classic pathological example): choosing augmenting paths through the capacity-1 edge repeatedly can force 2000 augmentations of size 1 each, despite the answer being reachable in 2 augmentations of size 1000. This is precisely the failure mode Edmonds-Karp's BFS rule eliminates, since shortest paths never route through unnecessarily long detours when a direct saturating path is available.

Common pitfalls & traps

PitfallWhy it happensFix
Forgetting reverse residual edgesTreating the graph as static, only decrementing forward capacityAlways maintain paired forward/backward residual edges; initialize reverse capacity to 0
Using DFS with arbitrary tie-breakingDFS can pick long, capacity-poor paths repeatedlyUse BFS (Edmonds-Karp) for guaranteed polynomial time, or scale capacities
Assuming termination with real-valued capacitiesGeneric method with adversarial path choice can loop forever on irrational inputsUse integer capacities, or a strongly-polynomial variant (Dinic's, BFS-based)
Confusing flow value with edge flow sumSumming all edge flows instead of net flow out of ssFlow value = net flow leaving ss (or entering tt), not total flow on all edges
Ignoring parallel edges / self-loopsResidual graph construction assumes simple capacity semanticsMerge parallel edges' capacities or handle them explicitly in the residual graph
Stopping too earlyTreating "no path found by one particular search" as "no path exists"Confirm true unreachability (BFS/DFS from ss over all positive-residual edges) before halting

Pioneers & history

The method is named for L. R. Ford Jr. and D. R. Fulkerson, whose 1956 RAND Corporation report on maximum flow in networks — motivated in part by Cold War-era transportation and logistics problems — introduced both the augmenting-path method and the max-flow min-cut theorem it certifies. Their monograph Flows in Networks (1962) became the founding text of network flow theory.

Origins · 1 minLester Randolph Ford Jr. and how this was discovered
LR
Lester Randolph Ford Jr.
1927–2017 · American mathematician, RAND Corporation, co-founder of network flow theory

Ford, together with Fulkerson, formalized the maximum flow problem and proved the max-flow min-cut theorem while working at RAND on problems related to Soviet railway network capacity — a Cold War logistics question repurposed into one of the deepest results in combinatorial optimization.

History
1956
— Ford and Fulkerson publish the augmenting-path method and max-flow min-cut theorem.
1962
— Flows in Networks monograph systematizes network flow theory.
1970
— Yefim Dinitz (Dinic) develops blocking-flow algorithm achieving O(V2E)O(V^2E).
1972
— Edmonds and Karp publish the BFS-refinement analysis giving the O(VE2)O(VE^2) bound.
1998
— Goldberg-Rao and later work push max-flow complexity toward near-linear time in special regimes.

Where this matters

Maximum flow computations underlie network routing and capacity planning in telecommunications, where link bandwidths act as capacities and traffic engineering seeks maximum throughput or robust cut structures. In computer vision, image segmentation via graph cuts (foreground/background separation) is solved as a min-cut/max-flow problem on a pixel-adjacency graph, with Ford-Fulkerson-style augmenting-path solvers (and specialized variants) at the core of tools used in medical imaging and photo editing software.

Bipartite matching — assigning workers to jobs, students to schools, or kidneys to transplant recipients — reduces directly to max flow with unit capacities, foreshadowing Bipartite Matching via Augmenting Paths, where each augmentation corresponds to finding one more compatible match. Airline crew scheduling and transportation logistics, the original motivating domain, still use flow-based formulations for capacity-constrained routing. Compiler and hardware design tools use min-cut computations (the dual output of Ford-Fulkerson) for circuit partitioning, minimizing the wires crossing a boundary. Even project selection and baseball elimination puzzles in combinatorial optimization courses are canonical max-flow reductions taught immediately after this method, building directly on the Max-Flow Min-Cut Theorem this article derives.

Ask the tutor: How does Dinic's algorithm use level graphs and blocking flows to beat Edmonds-Karp's running time?

Is Ford-Fulkerson an algorithm or a method — and why does the distinction matter?

It is called a method because it leaves one crucial decision unspecified: which augmenting path to use at each step. This isn't a pedantic distinction — the choice determines whether the procedure is fast, slow, or infinite. Generic Ford-Fulkerson with arbitrary path selection can require a number of iterations proportional to the numeric value of the max flow (pseudo-polynomial time), and with irrational capacities can fail to terminate entirely. Only once you fix a specific path-selection rule — BFS shortest paths (Edmonds-Karp), maximum bottleneck capacity (capacity scaling), or blocking flows (Dinic's) — does it become a fully specified algorithm with a provable complexity bound. This article treats Edmonds-Karp as the canonical, well-behaved instantiation.

Why does augmenting along a path always preserve flow feasibility?

Feasibility requires two things: capacity constraints and flow conservation. Augmenting by the bottleneck amount never exceeds any edge's residual capacity, since the bottleneck is defined as the minimum residual capacity along the path — so capacity constraints hold by construction. Conservation holds because every intermediate vertex on the path receives exactly as much extra flow in as it sends out (the same augmentation amount passes through), so the net flow at each intermediate vertex is unchanged. Only ss (net outflow increases) and tt (net inflow increases) see their totals change, which is exactly the desired effect of increasing the flow value.

How does the residual graph handle undirected edges or edges in both directions between two vertices?

An undirected edge with capacity cc is typically modeled as two directed edges, u→vu \to v and v→uv \to u, each with capacity cc, allowing flow in either direction (but not simultaneously exceeding cc net in one direction under standard formulations). If the original graph already has both (u,v)(u,v) and (v,u)(v,u) as directed edges with their own capacities, care must be taken in the residual graph representation — often by using four "edges" (two originals, two reversals) or by tracking net flow f(u,v)−f(v,u)f(u,v) - f(v,u) with a single combined variable. Implementations typically use an adjacency-list-of-edge-objects representation, where each edge object stores its capacity, current flow, and a pointer to its paired reverse edge, avoiding ambiguity.

What is the relationship between Ford-Fulkerson and the Max-Flow Min-Cut Theorem?

Ford-Fulkerson's termination condition is the constructive proof of the theorem. When no augmenting path remains, the set of vertices reachable from ss in the residual graph defines a cut whose capacity exactly equals the current flow value. Since flow value never exceeds any cut's capacity (a general fact independent of the algorithm), matching a specific cut's capacity certifies optimality. So running Ford-Fulkerson to completion doesn't just compute a number — it exhibits a min cut as a certificate, which is why the theorem and the method are historically and logically inseparable.

Why is Edmonds-Karp's O(VE^2) bound considered good, given that faster algorithms exist?

O(VE^2) is polynomial and capacity-independent, a qualitative leap over the pseudo-polynomial generic method — this was itself a notable result in 1972. It is not the fastest known: Dinic's algorithm improves this to O(V^2E) using blocking flows over level graphs, and push-relabel methods and more recent near-linear-time algorithms (for various capacity/graph regimes) do better still on large or dense graphs. Edmonds-Karp remains pedagogically central because its proof technique — the monotonic non-decrease of shortest-path distances — is the direct ancestor of the level-graph arguments used in faster algorithms, making it the natural first stop before those more advanced methods.

Can Ford-Fulkerson handle graphs with cycles or multiple paths between the same pair of vertices?

Yes — the method makes no assumption of acyclicity. Cycles in the original graph simply become part of the residual graph, and BFS or DFS path-finding naturally avoids revisiting vertices within a single augmenting path search (standard graph search algorithms track visited vertices). If multiple parallel edges exist between two vertices, they should be either merged into a single edge with combined capacity or tracked as distinct residual edges, but the algorithm's correctness argument via cuts and conservation is unaffected either way, since it depends only on capacity and conservation constraints, not on the graph being a DAG.

Does the choice of augmenting path affect the final max flow value?

No — the maximum flow value is unique regardless of which sequence of augmenting paths is chosen, as long as the algorithm runs until no augmenting path remains (this follows from the max-flow min-cut argument, which applies to any terminating execution). However, the specific flow assignment achieving that value, and especially the specific minimum cut exposed at termination, can differ between runs if multiple minimum cuts exist. What path selection does affect is purely the running time: bad choices can blow up the number of iterations enormously, which is exactly the problem Edmonds-Karp's BFS rule fixes.

Before this

Where this leads