M-Coloring Problem
Can the graph's vertices be colored with at most m colors so no edge joins same-colored vertices?
Open on GeeksforGeeks ↗Intuition
Color vertices one at a time; a color is legal if no already-colored neighbour has it. If a vertex has no legal color, backtrack — the earlier assignment forced a dead end. First full assignment = yes.
Constraint-satisfaction backtracking: assign, verify, recurse, and undo on failure. The shape is the same as N-Queens — what changes is only the safe test. Notice it returns a boolean rather than collecting results, so the recursion can stop at the first success instead of exploring everything.
Approach
Assign vertex by vertex
At vertex v, try colors 1..m; safe checks colored neighbours only — later vertices don't constrain yet.
Backtrack on dead ends
If no color fits, unwind to the previous vertex and try its next color. The search tree covers all assignments but prunes hard.
Stop at the first success
The question is decision, not enumeration — return True the moment vertex n is passed.
Solution & live demo
Common pitfalls
Not undoing the assignment on failure
color[v] = c if solve(v + 1): return True
color[v] = c if solve(v + 1): return True color[v] = 0
A stale colour makes later branches see a constraint that was never actually committed, so valid colourings get rejected. Every assignment before a recursive call needs its inverse after.
Checking adjacency without checking the edge
return all(color[u] != c for u in range(n))
return all(not adj[v][u] or color[u] != c for u in range(n))
Only adjacent vertices are forbidden from sharing a colour. Comparing against every vertex demands all-distinct colours, which fails almost every solvable instance.
Ignoring the recursive return value
solve(v + 1) return True
if solve(v + 1): return True
Reporting success without checking whether the rest could actually be coloured returns True for impossible instances. The answer depends on the whole assignment completing, not just this vertex.
Edge cases
Greedy always succeeds; the search finds it immediately without backtracking.
Every ordering dead-ends; the search exhausts and returns False.