Bipartite Graph Check asks a simple-sounding question: can you split a graph's vertices into two groups so that every edge crosses between the groups? It is the graph version of a two-coloring puzzle, and BFS solves it in one sweep.
Problem. Given an undirected graph (as an adjacency list graph, where graph[u] lists the
neighbors of vertex u), return True if the graph is bipartite — its vertices can be colored
with two colors so that no edge connects two vertices of the same color.
Example: vertices 0..5 with edges 0-1, 0-3, 1-2, 2-5, 3-4, 4-5. Coloring {0, 2, 4} red and
{1, 3, 5} blue, every edge crosses colors → answer True.
The slow way first
You might try to guess a partition and check it: assign each vertex to one of two groups, then verify no edge stays inside a group. But there are 2^n ways to assign colors — trying them all is exponential and hopeless for anything but a tiny graph.
The question to ask: do I really have a choice once I pick a starting color? No. Once vertex 0 is red, all its neighbors are forced to be blue, their neighbors forced back to red, and so on. The coloring propagates with no guesswork — which is exactly what a traversal does.
The idea: color as you traverse
Run BFS from an uncolored vertex. Give it color 0. Every time you pop a vertex u and look at a neighbor v:
- if
vis uncolored, paint it the opposite color (1 - color[u]) and enqueue it; - if
vis already colored the same asu, you have found an edge inside one group — the graph is not bipartite, returnFalse.
If BFS finishes with no such clash, the two-coloring worked. (Loop over all start vertices so disconnected pieces are covered.)
The key insight: the color of every vertex is determined the moment its first neighbor is colored. We are not searching — we are propagating a forced choice and watching for a contradiction.
Walk through it
Step through the animation. Vertex 0 starts red. BFS colors 1 and 3 blue, then 2 and 4 red, then 5 blue. Each edge lights up as it is processed. Every edge connects a red to a blue, no clash ever appears, so the verdict is bipartite = True.
Pseudocode
color = empty map (vertex -> 0 or 1)
for each start vertex with no color yet:
color[start] = 0
queue = [start]
while queue is not empty:
u = pop front of queue
for each neighbor v of u:
if v has no color:
color[v] = 1 - color[u] # opposite color
add v to queue
else if color[v] == color[u]:
return False # same-color edge -> not bipartite
return TrueThe Python solution
def is_bipartite(graph):
color = {}
for start in range(len(graph)):
if start in color:
continue
color[start] = 0
queue = [start]
while queue:
u = queue.pop(0)
for v in graph[u]:
if v not in color:
color[v] = 1 - color[u]
queue.append(v)
elif color[v] == color[u]:
return False
return Truecolormaps each vertex to0or1; an absent key means uncolored.- The outer
for startloop restarts BFS on any vertex not yet reached, so disconnected components are all checked. queue.pop(0)takes the front of the queue — standard BFS order.- Line 12 is the propagation: a fresh neighbor gets
1 - color[u], the opposite color. - Lines 14-15 are the failure test — an already-colored neighbor sharing
u's color is an edge inside one group, so the graph cannot be bipartite.
Complexity
| Case | Time | Notes |
|---|---|---|
| Try all 2-colorings | O(2^n) (slow) | exponential, infeasible |
| BFS two-coloring | O(V + E) (moderate) | each vertex and edge once |
O(V) (moderate)We touch every vertex and every edge a constant number of times, so the traversal is linear in the size of the graph. The extra space is the color map plus the BFS queue, both O(V).
When this pattern shows up
Whenever a problem says "split into two groups," "no two adjacent can be the same," or "can these be scheduled into two slots," think two-coloring. The move is always the same: BFS or DFS from each component, assign the opposite color across every edge, and fail on the first same-color edge.
Do not forget the outer loop over all start vertices. A graph can be made of several disconnected
pieces; if you BFS from vertex 0 only, you may miss a same-color edge sitting in another component
and wrongly report True.
Practice
Vertex 0 is colored red (0). It has a neighbor 1 that is still uncolored. What color does 1 get, and what goes in the queue?
1. What makes a graph bipartite?
2. When does the BFS report that the graph is NOT bipartite?
3. Why does the algorithm loop over every start vertex?
4. What is the time complexity of the BFS two-coloring?