Possible Bipartition
Given n people and pairs who dislike each other, decide if they can be split into two groups so no two people in the same group dislike each other.
Open on LeetCode ↗Intuition
The trap is assuming everyone forms one connected group and only coloring starting from person 1. The dislikes graph can split into several disconnected pieces, so a fresh BFS or DFS must start from every uncolored person, not just the first. Within each piece, color a person, force every disliked neighbor to the opposite team, and repeat -- exactly the 2-coloring test for bipartiteness. A conflict is found the moment a neighbor is already colored the SAME as the current person, which is impossible to fix and immediately rules out any valid split.
Two-colouring a graph: neighbours must differ, and a conflict proves an odd cycle exists. The outer loop over every vertex handles disconnected components, which is the detail most single-BFS attempts miss.
Approach
Build the dislikes graph
For every pair [a, b], add an undirected edge -- each dislikes the other, so the adjacency list gets both directions.
Color every disconnected group
Loop over every person; if uncolored, that person starts a brand new group (the graph may not be connected). BFS/DFS from there, coloring team A/B and alternating for each newly reached neighbor.
Detect the same-color conflict
When a BFS step reaches a neighbor that is already colored, check its color: if it matches the current person's color, two people who dislike each other ended up on the same team -- return false immediately.
Solution & live demo
Common pitfalls
Colouring from vertex 1 only
queue = [1] # single BFS
for start in range(1, n + 1):
if color[start]: continueThe dislike graph is often disconnected, so a single traversal leaves whole components uncoloured and their conflicts undetected. Every uncoloured vertex must seed a new traversal.
Using 0 as a colour
color = [0] * (n + 1) color[start] = 0
color[start] = 1 color[v] = -color[u]
0 doubles as "uncoloured", so a vertex painted 0 looks unvisited and gets re-queued or re-painted. Using 1 and −1 keeps the sentinel distinct and makes negation the recolouring operation.
Only checking neighbours that are uncoloured
if not color[v]:
color[v] = -color[u]
queue.append(v)elif color[v] == color[u]:
return FalseAn already-coloured neighbour is exactly where a conflict shows up. Skipping those cases means the algorithm colours the graph happily and never detects the odd cycle that makes bipartition impossible.
Edge cases
Outer loop restarts coloring at every uncolored person, not just person 1.
Trivially colored alone; never causes a conflict.
Coloring wraps around and forces a same-color conflict -- correctly reported impossible.
Every person its own group -- always possible.