Maximum multicommodity flow
Let G=(V,E) be a directed graph and let P be a (possibly large) collection of paths through the graph.
A multicommodity flow f assigns a flow f(p) to each path p∈ P.
The size of the flow, |f|, is the total flow assigned: ∑p∈ P f(p).
We let f(e) for any edge e denote the total flow sent across edge e: f(e) = ∑p∈ P, p∋ e f(p).
The congestion of the flow, cong(f), is the maximum amount of 
flow crossing any edge: maxe∈ E f(e).
Given a budget C, the goal is to find a flow of congestion at most C
maximizing the size of the flow.
Algorithm (given ε > 0):
 1. Let f(p) = 0 for each p ∈ P.
 2. Repeat until cong(f) = C :
 3.    Choose a path p ∈ P minimizing ∑e∈ p (1+ε)f(e).
 4.    Let f(p) = f(p) + 1.  (Send a unit of flow along P.)
 5. Return f.
thm: Assuming C ≥ \ln(m)/ε2 and ε ≤ 1/2 the algorithm returns a flow of size at least (1-O(ε)) OPT.
proof: 
- Note if we could increase the congestion by at most C/|f*| in each iteration, we would converge to a minimum-congestion flow  in about |f*| rounds.  However, this is not possible (consider the first round, we increase congestion by 1 no matter what).
-  Define φ(f) = ln1+ε ∑e∈ E (1+ε)f(e). Note that cong(f) ≤ φ(f).
-  φ is a "smooth" approximation of the congestion.  The idea is that the algorithm chooses the path p in each iteration to (approximately) minimize  the increase in φ (as a proxy for minimizing the increase in the congestion). 
-  Fix an iteration t.  Let p denote the chosen path and let ψ(e) = (1+ε)f(e) at the start of the iteration.  Then,  using log1+ε(1+z) ≤ (1+O(ε))z for ε < 1/2,
-   φ(ft) - φ(ft-1)  = ln1+ε[ 1 + ε ∑e∈ p ψ(e) / ∑e ψ(e)]  ≤ [1+O(ε)] ∑e∈ p ψ(e) / ∑e ψ(e).
 
-  Let f* be a maximum size flow of congestion at most C.  Define a probability distribution Pr on the paths by Pr(p) = f*(p)/|f*|.  If we choose a path p at random according to this probability distribution,  and send 1 unit of flow along p, then the probability that a given edge e is on p  is ∑p∋ e f*(p)/|f*| ≤ C/|f*|.  Thus, if we were to choose a random path p during an iteration, φ would increase   in expectation by  at most [1+O(ε)] C/|f*|].
-  Since the algorithm chooses p to minimize the increase in φ with each iteration,  φ(f) increases by at most [1+O(ε)]] C/|f*|] each iteration.  Thus, the algorithm maintains the invariant:
-   φ(f) ≤ O(ln(m)/ε) + [1+O(ε)] C |f|/|f*|].
 
-  At the end, φ(f) ≥ C (because cong(f)≤ φ(f)) so
-   C ≤ O(ln(m)/ε) + [1+O(ε)] C |f|/|f*|].
 
- Rewriting and using 1/[1+O(ε)] = 1-O(ε) for ε < 1/2,
-  |f|/|f*| ≥ 1-O(ε) - O(ln(m)/(ε C)).
 
References: