A Bit of History
Jack Edmonds published "Paths, Trees, and Flowers" in 1965, introducing the Blossom Algorithm to solve maximum matching in general graphs — those that need not be bipartite, extending the theory from Part 16 and the Hopcroft-Karp deep dive, both of which apply only to the bipartite case. The paper is doubly historic: beyond the algorithm itself, Edmonds used it to informally articulate what "efficient algorithm" should mean — polynomial-time computability — a conceptual cornerstone that helped shape the entire later field of computational complexity theory, including the eventual formal definitions of the classes P and NP.
Matching Foundations
A matching $M$ is a set of edges that share no endpoints. A vertex not incident to an edge of $M$ is exposed (or free). The search does not directly hunt for a larger matching; it hunts for a certificate that the current one can grow.
Edges switch status
The path alternates between edges outside $M$ and edges inside $M$. Starting from an exposed vertex, the first edge is unmatched.
Both endpoints are exposed
Flipping every edge on the path—matched becomes unmatched and vice versa—adds exactly one edge to $M$.
Berge's Theorem
A matching is maximum if and only if no augmenting path exists. This converts an optimization problem into a repeated search problem: find one augmenting path, flip it, and repeat.
Working Principle
A bipartite search grows an alternating forest from exposed roots. Its vertices have a parity label:
Even distance from a root
Explore unmatched edges leaving outer vertices. Every exposed root is outer.
Odd distance from a root
When an inner vertex is matched, immediately add its matched partner as an outer vertex.
In a bipartite graph, an edge between two outer vertices either joins two trees and exposes an augmenting path, or cannot occur within one alternating tree. In a general graph it can occur inside one tree. The two tree paths plus that edge form an odd alternating cycle: a blossom.
Edmonds' move is to contract that entire odd cycle into one super-vertex, continue the search in the smaller graph, and later lift any discovered augmenting path through the original cycle.
Key Insight
An odd cycle has two routes from its base to any chosen exit; exactly one has the alternating parity needed by the surrounding path. Contraction postpones that local choice. Lifting makes it later, once the entry and exit are known.
Detecting a Blossom
Suppose the search scans an unmatched edge $(u,v)$ joining two outer vertices in the same alternating tree. Let $b$ be the lowest common ancestor of $u$ and $v$ after current contractions. The path $b \leadsto u$, edge $(u,v)$, and path $v \leadsto b$ form an odd cycle. Vertex $b$ is its base.
- Walk from $u$ and $v$ toward $b$ through alternating-tree parent and matched-partner links.
- Mark every base encountered on those two branches as part of the blossom.
- Assign all marked vertices the common base $b$ and queue newly exposed outer representatives.
- Continue the same breadth-first search on the implicitly contracted graph.
Zoom Out, Then Zoom Back In
From far away, the odd cycle is one junction with several roads entering it. After the global route chooses which roads matter, zoom back in and select the alternating half of the cycle that connects them.
Worked Example: Contract, Search, Lift
Use six vertices $s,a,b,c,d,t$ and current matching $M=\{ab,cd\}$. Vertices $s$ and $t$ are exposed. Edges $bc$, $bd$, and $cd$ form a triangular blossom with base $b$; the alternating tree reaches $b$ through $s-a-b$.
Flipping the lifted path replaces $ab$ and $cd$ with $sa$, $bd$, and $ct$. The matching grows from 2 edges to 3, and every vertex is now matched.
Correctness
1. Flipping an augmenting path is safe
Every internal vertex of an augmenting path is incident to one matched and one unmatched path edge. After the flip it still has exactly one matched edge. The exposed endpoints each gain one, so the result is a matching of size $|M|+1$.
2. The blossom lemma preserves the search
Let $B$ be a blossom and $G/B$ the graph formed by contracting it to one vertex. An augmenting path exists in $G$ exactly when one exists in $G/B$. One direction is immediate: contract the portion of a path inside $B$. For the reverse direction, if a contracted path touches the super-vertex, expand $B$ and choose the one of the two routes around its odd cycle whose parity continues the alternating pattern. The blossom base anchors this lift.
3. No augmenting path means maximum
Repeated contraction lets the search either find and lift an augmenting path or prove none exists. Each successful augmentation increases $|M|$, and at most $\lfloor V/2\rfloor$ edges can be matched. When the search finally fails, Berge's theorem certifies that the matching is maximum.
What Contraction Preserves
Contraction does not claim that all vertices of the cycle are interchangeable in every graph problem. It preserves the specific yes/no question needed here: whether an augmenting path exists relative to the current matching.
Complexity Analysis
The array-based implementation below performs at most $O(V)$ augmenting searches. Its repeated scans for bases and contraction membership give the familiar bound:
$$\text{Time: } O(V^3) \qquad \text{Space: } O(V+E)$$
This is a practical teaching implementation for unweighted maximum-cardinality matching. The Micali–Vazirani algorithm improves unweighted general matching to $O(E\sqrt V)$, but is considerably more intricate. Minimum- or maximum-weight matching requires the weighted blossom family, with dual variables and tight-edge conditions; it is not obtained by attaching weights to this BFS.
| Problem | Typical algorithm | Representative bound |
|---|---|---|
| Bipartite, unweighted | Hopcroft–Karp | $O(E\sqrt V)$ |
| General, unweighted | Classic blossom implementation below | $O(V^3)$ |
| General, unweighted (advanced) | Micali–Vazirani | $O(E\sqrt V)$ |
| General, weighted | Primal–dual weighted blossom | Different algorithm and invariants |
Implementation
The code performs one BFS-style augmenting-path search from each currently exposed root. Contraction is implicit: vertices stay in the original adjacency lists, while base[v] says which super-vertex currently represents them.
| State | Meaning | Invariant |
|---|---|---|
match[v] | Current partner, or -1 | match[match[v]] == v |
p[v] | Predecessor in the alternating forest | Used to reconstruct and flip a path |
base[v] | Representative after contractions | Equal bases belong to one contracted blossom |
used[v] | Outer vertex queued for BFS | Only outer vertices expand unmatched edges |
blossom[v] | Temporary contraction mark | Cleared for each newly detected blossom |
Scope of These Listings
They solve maximum-cardinality matching in an undirected, unweighted graph. Self-loops should be ignored; parallel edges do not improve cardinality and may be deduplicated. For weighted matching, use a vetted weighted-blossom implementation.
Real-World Applications
Christofides' algorithm
Its TSP guarantee requires a minimum-weight perfect matching among odd-degree tree vertices. That invokes the weighted blossom family, not the unweighted listing above.
Any-to-any pairing
When participants are not naturally split into left and right groups, compatibility forms a general graph. Maximum matching finds the largest set of disjoint acceptable pairs.
Molecular graph analysis
Perfect and maximum matchings help model bond-assignment structures in molecular graphs, where odd cycles make bipartite-only methods insufficient.
Graph optimization libraries
General matching is a reusable primitive for factor problems, edge covers, and reductions in combinatorial optimization. Production code typically relies on a vetted implementation.
Which Matching Algorithm Do You Need?
| Input structure | Goal | Natural choice |
|---|---|---|
| Bipartite graph | Maximum cardinality | Hopcroft–Karp |
| General graph | Maximum cardinality | Unweighted blossom |
| General graph with edge costs | Minimum/maximum weight | Weighted blossom / primal–dual method |
| Need only feasibility of a perfect matching | Match every vertex | Run general matching and test $2|M|=V$ |
Pitfalls & Debugging
Five Common Misreadings
- “Every odd cycle is a blossom.” A blossom is an odd alternating cycle relative to the current matching and search forest.
- “Contract the graph permanently.” Contractions are search state. After augmentation, rebuild the forest for the changed matching.
- “The cycle can be expanded either way.” Only one side has the parity needed to continue the alternating path.
- “One contraction is enough.” Blossoms may be nested, overlap across searches, and appear only after earlier contractions.
- “Weights are a small extension.” Weighted blossom requires dual feasibility and tight-edge bookkeeping absent here.
Postconditions Worth Testing
- For every matched vertex $v$,
match[match[v]] == v. - No vertex is matched to itself, and every reported pair is an input edge.
- The count
sum(match[v] != -1) / 2equals the number of matching edges. - On small random graphs, compare against an exhaustive subset search; this is especially effective for exposing nested-blossom bugs.
Exercises
- Flip: verify that symmetric difference with any augmenting path increases the matching size by exactly one.
- Trace: for the six-vertex example, label every alternating-tree vertex outer or inner before the triangle contracts.
- Lift: show why the alternative route $b-c$ cannot replace $b-d-c$ in the lifted path.
- Bipartite case: explain why an edge joining two outer vertices in the same alternating tree would imply an odd cycle.
- Testing challenge: generate all simple graphs on at most six vertices and compare the implementation with brute-force maximum matching.
Mental Model to Keep
An odd alternating cycle creates two possible internal routes whose parity is ambiguous too early. Contract the cycle to delay that choice, find the global augmenting path, then expand the cycle and choose the parity-correct route.