12.23 Complexity Analysis
Flow algorithms solve the same abstract problem, but their running times differ sharply.
12.23 Complexity Analysis
Problem
Flow algorithms solve the same abstract problem, but their running times differ sharply.
A small network can be solved with almost any implementation. A large scheduling system, matching engine, or transportation model may require careful algorithm selection. The wrong choice can turn a feasible computation into an unusable one.
You need a way to compare flow algorithms by graph size, capacity size, density, and problem structure.
Solution
Analyze a flow problem using four quantities:
V = number of vertices
E = number of edges
F = value of the maximum flow
C = maximum edge capacity
Then choose the algorithm whose bound matches the structure of the graph.
The most common algorithms have these bounds:
| Algorithm | Typical Bound | Best Use |
|---|---|---|
| Ford-Fulkerson | O(EF) | Small integer-capacity graphs |
| Edmonds-Karp | O(VE²) | Simple, predictable baseline |
| Dinic | O(V²E) | General-purpose max flow |
| Dinic on unit networks | O(E√V) or better | Matching and disjoint paths |
| Push-relabel | O(V²E) generic | Dense graphs and practical solvers |
| Min-cost flow with Bellman-Ford | O(FVE) | Small graphs with negative costs |
| Min-cost flow with potentials | O(FE log V) | Sparse graphs with costs |
These are worst-case bounds. Practical performance depends heavily on implementation details, graph shape, and capacity distribution.
Ford-Fulkerson
Ford-Fulkerson repeatedly finds any augmenting path.
If capacities are integers, each augmentation increases the flow by at least one unit.
Each path search costs:
O(E)
Number of augmentations:
O(F)
Total:
O(EF)
This bound depends on the value of the flow, not just the size of the graph.
If capacities are large, this can be poor.
Example:
E = 1,000
F = 1,000,000,000
The bound becomes impractical.
Ford-Fulkerson is acceptable when capacities are small and the implementation must be minimal.
Edmonds-Karp
Edmonds-Karp is Ford-Fulkerson with BFS path selection.
Each BFS costs:
O(E)
The number of augmentations is:
O(VE)
Total:
O(VE²)
The advantage is that the bound no longer depends on the numeric flow value.
This matters when capacities are large.
The disadvantage is that Edmonds-Karp still performs one augmentation per BFS. For large graphs, it is often slower than Dinic.
Dinic
Dinic alternates between BFS level-graph construction and DFS blocking-flow computation.
For general graphs, the usual bound is:
O(V²E)
This is often better than Edmonds-Karp, especially when E is large.
Dinic is a strong default choice because it is:
- fast in practice
- not too difficult to implement
- effective on sparse graphs
- excellent on many unit-capacity problems
Dinic on Unit Networks
When every capacity is:
0 or 1
Dinic becomes faster.
This appears in:
- bipartite matching
- edge-disjoint paths
- vertex-disjoint paths after node splitting
- unit-capacity scheduling models
For many such graphs, the bound improves to roughly:
O(E√V)
This is why Dinic performs well as a generic replacement for specialized matching algorithms in many programming-contest settings.
Push-Relabel
Push-relabel has the same broad worst-case family as Dinic in many presentations:
O(V²E)
but its practical behavior can be excellent, especially on dense graphs.
The algorithm does not search for full augmenting paths. It moves excess flow locally.
Its performance depends heavily on heuristics:
- highest-label selection
- gap relabeling
- global relabeling
- efficient active-vertex queues
A simple push-relabel implementation may be slower than Dinic. A tuned implementation can be very fast.
Graph Density
Graph density changes everything.
A sparse graph has:
E ≈ V
A dense graph has:
E ≈ V²
For Edmonds-Karp:
O(VE²)
Sparse case:
O(V³)
Dense case:
O(V⁵)
For Dinic:
O(V²E)
Sparse case:
O(V³)
Dense case:
O(V⁴)
This is one reason Edmonds-Karp is rarely used for large dense graphs.
Capacity Size
Capacity size affects algorithms differently.
Ford-Fulkerson depends on:
F
so large capacities can be dangerous.
Edmonds-Karp, Dinic, and push-relabel are strongly polynomial in the graph size for ordinary max flow. Their standard bounds do not depend directly on the numeric capacity values.
However, large capacities still affect implementation:
- use 64-bit integers
- avoid overflow in sums
- choose infinity carefully
- avoid multiplying flow and cost in 32-bit arithmetic
Min-Cost Flow
Min-cost flow is usually more expensive than max flow.
The successive shortest path method sends flow along cheapest residual paths.
If it augments one unit at a time, the number of augmentations may be:
F
Using Bellman-Ford for each shortest path:
O(FVE)
Using Dijkstra with potentials:
O(FE log V)
The potential-based version is usually preferred for sparse graphs.
If capacities are large and augmentations can push large bottlenecks, performance improves. If every augmentation pushes only one unit, cost can dominate.
Matching Complexity
Bipartite matching has special structure.
| Algorithm | Complexity |
|---|---|
| Simple augmenting path | O(VE) |
| Hopcroft-Karp | O(E√V) |
| Dinic on unit network | O(E√V) |
Use Hopcroft-Karp when the problem is exactly bipartite matching.
Use Dinic when the matching is part of a larger flow model.
Use min-cost flow when assignments have costs, quotas, or richer constraints.
Lower Bounds and Circulation
Lower-bound transformations add:
2
vertices for the super source and super sink, plus at most:
V
extra edges.
So the transformed graph has:
V' = V + 2
E' = E + O(V)
The asymptotic complexity remains essentially the complexity of the chosen max-flow algorithm on the transformed graph.
The transformation itself is linear:
O(V + E)
Node Splitting
Vertex-capacity and vertex-disjoint-path models often split every vertex.
This changes graph size to:
V' = 2V
E' = E + V
The graph remains linear in the size of the original graph.
But constants matter. If the original graph is already large, node splitting doubles memory usage and can noticeably increase runtime.
Memory Complexity
Most flow implementations use adjacency lists with explicit reverse edges.
Every logical edge creates two stored edges:
forward edge
reverse edge
Memory is:
O(V + E)
but the constant factor is roughly doubled.
For min-cost flow, each edge also stores cost.
For lower-bound recovery, you may also store original edge indices.
A typical edge structure contains:
to
reverse index
capacity
cost
or:
to
reverse index
capacity
for ordinary max flow.
Choosing an Algorithm
Use this decision guide:
| Problem Type | Good Default |
|---|---|
| Small max-flow problem | Edmonds-Karp or Dinic |
| General max flow | Dinic |
| Dense max flow | Push-relabel |
| Bipartite matching | Hopcroft-Karp |
| Matching inside larger flow model | Dinic |
| Assignment with costs | Hungarian or min-cost flow |
| General costs and capacities | Min-cost flow with potentials |
| Lower bounds and demands | Circulation plus Dinic |
| Disjoint paths | Unit-capacity max flow |
The best algorithm is not always the one with the strongest theoretical bound. Simplicity, correctness, and implementation reliability matter.
Practical Benchmarking
For production use, benchmark with realistic data.
Synthetic worst cases are useful, but real flow networks often have structure:
- layered graphs
- low degree
- many unit capacities
- skewed demands
- sparse eligibility edges
- repeated similar instances
An algorithm that looks inferior on paper may perform well on the actual workload.
Measure:
build time
solve time
memory use
number of augmentations or phases
For min-cost flow, also measure shortest-path iterations.
Common Mistakes
Comparing Bounds Without Graph Shape
O(V²E) and O(VE²) mean different things on sparse and dense graphs.
Ignoring Flow Value
Ford-Fulkerson can be fast when F is small and terrible when F is large.
Forgetting Transformation Costs
Node splitting, lower bounds, and time expansion can multiply graph size.
Using 32-Bit Arithmetic
Flow values, capacities, and total costs often exceed 32-bit limits.
Optimizing Too Early
A clear Dinic implementation is often sufficient. Start there unless the problem structure strongly suggests another algorithm.
Discussion
Complexity analysis for flow algorithms has two layers. The first is the algorithmic bound. The second is the modeling expansion required before the algorithm runs.
A scheduling problem may start with 100 workers and 50 shifts, but after time expansion, skill layers, and lower-bound constraints, the actual graph may contain thousands of nodes and edges. The complexity of the solver applies to that transformed graph, not the original problem statement.
This is why flow modeling and complexity analysis should be done together.
Takeaway
Analyze flow algorithms using graph size, edge count, flow value, capacity size, and model transformations. Ford-Fulkerson depends on flow value. Edmonds-Karp is predictable but often slow. Dinic is the standard general-purpose choice. Push-relabel is strong on dense networks. Hopcroft-Karp is specialized for bipartite matching. Min-cost flow is more expensive but more expressive.
Choose the simplest algorithm that comfortably fits the transformed graph you actually intend to solve.