A graph is bipartite iff it has no odd cycle iff it is 2-colourable. Test with BFS/DFS colouring per component, or online with a parity DSU. Bipartiteness unlocks the matching toolbox: König (min vertex cover = max matching), max independent set matching, Hall’s condition, Dilworth for posets (Bipartite Matching).
// returns colours (0/1), or an odd cycle if the graph isn't bipartite
pair<vector<int>, vector<int>> twoColour(const vector<vector<int>>& g) {
int n = sz(g); vector<int> c(n, -1), par(n, -1), dep(n);
for (int s = 0; s < n; s++) {
if (c[s] >= 0) continue;
c[s] = 0; queue<int> q; q.push(s);
while (sz(q)) {
int u = q.front(); q.pop();
for (int v : g[u]) {
if (c[v] < 0) { c[v] = c[u] ^ 1, par[v] = u, dep[v] = dep[u] + 1, q.push(v); continue; }
if (c[v] != c[u]) continue;
vector<int> a{u}, b{v}; // climb to the common ancestor
while (a.back() != b.back()) {
if (dep[a.back()] >= dep[b.back()]) a.push_back(par[a.back()]); else b.push_back(par[b.back()]);
}
b.pop_back(); a.insert(a.end(), b.rbegin(), b.rend());
return {{}, a}; // odd cycle u ... lca ... v (edge v-u closes it)
}
}
}
return {c, {}};
}Proof: bipartite iff no odd cycle, and the extracted cycle is odd
A cycle in a bipartite graph alternates sides, so it has even length. Conversely, BFS-colour each component by depth parity. If an edge joins two vertices of the same colour, their depths have equal parity; the tree paths from and to their lowest common ancestor have lengths and , of equal parity, so together with the edge they form a closed walk of odd length , which is a simple cycle because the two tree paths meet only at . If no such edge exists, the colouring is proper.
Online and offline variants
- Parity DSU: each vertex stores its parity relative to its root; uniting requires opposite parities; an edge inside a component with equal parities creates an odd cycle. Supports “is the graph still bipartite after each added edge” in near-constant time (DSU).
- With deletions (offline): segment tree over time with a rollback parity DSU, (CF 813F).
- Edges in a range of indices (“is the subgraph of edges bipartite?”): two pointers on the largest bipartite window with rollback or a link-cut tree maintaining a maximum spanning forest by deletion time; or the divide-and-conquer “minimal for each ” monotonicity (JOI “Joker”).
The parity / double-cover trick
To ask about walks of a given parity (“is there a walk of odd length from to ”, “shortest odd walk”, “reach in exactly steps for huge ”), BFS on the bipartite double cover: vertices , edges . In a connected non-bipartite graph, every vertex is reachable with both parities; walks of length exactly exist iff the shortest walk of the right parity has length (pad with back-and-forth steps).
Proof: padding walks
A walk can be extended by 2 by going along any edge and back, so if a walk of length from to exists, so do walks of lengths . Hence the set of achievable lengths of a given parity is exactly where is the shortest walk of that parity, which is the BFS distance to in the double cover.
Where bipartite structure hides
- grids (chessboard colouring): no two adjacent cells chosen = independent set; domino placement = matching;
- rows vs columns: placing rooks, “one marked cell per row and column”;
- trees and forests (depth parity);
- even/odd sums: “no two chosen numbers sum to a prime” splits by parity (primes are odd);
- left/right parts of a DAG path cover;
- positions vs values of a permutation.
Facts about bipartite graphs
| Fact | Statement |
|---|---|
| König | max matching = min vertex cover |
| Gallai | max independent set + min vertex cover (any graph) |
| König (edges) | min edge cover = − max matching (no isolated vertices) |
| Hall | a matching saturating exists iff for all |
| regular bipartite | every -regular bipartite graph () has a perfect matching; its edges split into perfect matchings |
| edge colouring | bipartite graphs are -edge-colourable (König’s line colouring theorem) (Colouring) |
| counting | perfect matchings = permanent of the biadjacency matrix: p-hard in general, by Ryser |
Proofs of the matching theorems are in Bipartite Matching.
Bipartiteness is exactly the boundary between easy and hard for several of these: -colouring for is NP-complete (even restricted to planar graphs, even for , Colouring), and general-graph matching/vertex-cover/independent-set lose their polynomial algorithms or become NP-hard outright (vertex cover and independent set; matching stays polynomial via Blossom, just slower):
| Quantity | Bipartite | General |
|---|---|---|
| maximum matching | (Hopcroft–Karp) | (Blossom) |
| minimum vertex cover | max matching (König) | NP-hard |
| maximum independent set | max matching | NP-hard |
| min-cost perfect matching | (Hungarian) | (weighted Blossom) |
Odd cycle transversal: the minimum number of vertices to delete to make a graph bipartite. NP-hard in general, but fixed-parameter tractable in the number of vertices deleted.