E ExamMaster

CS Core & Software Engineering · Data Structures & Algorithms

Graph Colouring by Backtracking

m-colouring as a search: assign each vertex a colour in 1..m, abandon a partial colouring the moment a neighbour clash appears. Distinct from the chromatic-number decision…

Four concepts on graph colouring as search — the assignment problem versus the NPC decision, the choose-check-unchoose loop, a 3-colouring of the square-plus-diagonal, and why m=2 is BFS instead. N-Queens and subsets stay in recursion and backtracking; chromatic-number decision stays in NP-complete graph problems.

  • CS Core & Software Engineering
  • Medium level
  • 4 concepts

2Try a colour, check neighbours, unchoose

Fix an order of the vertices, v_0,\ldots,v_{n-1}. At v_i try each colour c \in \{1,\ldots,m\}. A colour is legal when no already-coloured neighbour of v_i holds c. If it is legal, assign it, recurse to v_{i+1}, then unassign it and try the next c. Success at i=n is a complete colouring.

That is the same choose-explore-unchoose skeleton as N-Queens. The clash test is the only new piece: a neighbour's colour, not a shared column or diagonal.

Triangle A-B-C. A takes colour 1. B is refused colour 1 then takes colour 2. C is refused both colours and marked with a cross. B and A unchoose and the triangle returns to empty.
m=2 on a triangle: try a colour, clash with a neighbour, unchoose. Two colours cannot colour K3.

One vertex

  1. Try cEach colour in 1..m.
  2. Clash?Reject c if some neighbour already holds c.
  3. UnchooseOn failure of the recursive call, clear v_i and try the next c.

m-colouring

def colour(graph, m):
    n = len(graph)
    col = [0] * n

    def ok(v, c):
        return all(col[u] != c for u in graph[v])

    def rec(v):
        if v == n:
            return True
        for c in range(1, m + 1):
            if ok(v, c):
                col[v] = c
                if rec(v + 1):
                    return True
                col[v] = 0
        return False

    return col if rec(0) else None
When vertex v_i tries colour c, the clash test looks at
  1. Already-coloured neighbours of v_i
  2. Every vertex in the graph, including those not yet coloured
  3. Only the previous vertex v_{i-1}

Uncoloured neighbours have colour 0 and do not clash. A non-neighbour never clashes. Restricting the test to v_{i-1} would miss the rest of the adjacency list.

3Triangle plus a pendant-free D, m = 3

Running graph: vertices A, B, C, D. Edges AB, BC, CD, DA, AC. A, B, C are a triangle, so m=2 is impossible. D is adjacent to A and C only.

Order A, B, C, D. A=1, B=2 (1 clashes with A), C=3 (1 and 2 taken by neighbours A and B), D=2 (1 and 3 taken by A and C; 2 is free because DB is not an edge). First success: (1,2,3,2).

Figure. Triangle ABC uses three colours. D reuses B's colour 2 because the edge DB is absent. Roles mark c1 / c2 / c3, not good versus bad.

First successful branch

  1. A, BA=1. B rejects 1, takes 2.
  2. CNeighbours A,B hold 1,2 — C takes 3.
  3. DNeighbours A,C hold 1,3 — D takes 2.

Why D may reuse 2

After A=1, B=2, C=3, which colours are illegal for D, and why is 2 legal?

  • neighbours of DA and C (not B)
  • colours on A, C1 and 3
  • colour 2 on Dlegal — no edge DB
  • assignmentA1 B2 C3 D2

Pro tip. If the missing edge were AB instead of DB, the triangle would sit elsewhere and the first success would be a different 4-tuple. The clash test follows the edges you actually have.

Coding lab. 3-colour the square plus diagonal runs in the app, with checks on your output.

On the running graph with m=3, D can take colour 2 because
  1. D is not adjacent to B, who already holds 2
  2. Any leftover colour is legal, even on a neighbour
  3. m=3 always lets the last vertex reuse colour 1

Legality is 'no neighbour holds this colour'. A and C hold 1 and 3. Reusing 1 would clash with A.

4Prune on a clash; do not backtrack 2-colouring

A colour that already sits on a neighbour is rejected before the recursive call. That prune is the whole speedup: the subtree in which v_i holds a clashing c is empty of solutions, so it is not explored. On the running graph, B never tries colour 1; C never tries 1 or 2.

When m=2, do not run this tree. A graph is 2-colourable if and only if it is bipartite, and BFS (or DFS) 2-colours each component or reports an odd cycle in linear time. The running graph has a triangle, so BFS reports failure without a 2^4 search. Backtracking is the tool for a general m, usually m \ge 3.

Same A-B-C-D figure. For m=2 the triangle is an odd cycle; BFS reports that without growing a 16-leaf tree.

Pick the algorithm

  1. m=2BFS 2-colour. Odd cycle → no.
  2. m \ge 3, small nBacktracking as in the listing.
  3. Large n, m \ge 3Exact search may be hopeless; that is the NPC sentence, not a new proof.

m = 2 dies at C

Same graph, m=2. After A=1, B=2, which colours can C try, and what does the search return?

  • C's neighbours A, Bcolours 1 and 2 — both of m
  • legal colours for Cnone
  • unchoose B, try B=1clashes with A immediately
  • search resultno 2-colouring

Pro tip. BFS would have said the same thing after seeing the odd cycle ABC. The backtracking tree is the long way to that one fact when m=2.

2-colouring a graph should be done by
  1. BFS (or DFS) bipartiteness, in linear time
  2. The m-colouring backtracking tree with m=2
  3. A reduction from SAT

2-colouring is in P. The backtracking tree works but is the wrong tool. SAT reductions are for hardness proofs, not for colouring a given instance.

Notes

  • A proper m-colouring assigns each vertex a colour in \{1,\ldots,m\} so that every edge is bichromatic. The search problem is: produce such an assignment, or report that none exists.
  • Backtracking tries a colour for vertex v, checks that no already-coloured neighbour shares it, recurses to v+1, then unchooses the colour. The first clash prunes the whole subtree.
  • 2-colouring is not this tree: it is the bipartite BFS already named under chromatic-number decision. Use backtracking for a general m, typically m ≥ 3.
  • The decision 'does a k-colouring exist?' for k ≥ 3 is NP-complete. This topic is the exponential search you run on a small graph after that sentence, not a second NPC proof.
  • N-Queens is the same choose-explore-unchoose skeleton with a different clash test. Colouring's clash test is 'this colour already sits on a neighbour'.

Formulas

  • At most m^n assignments, n vertices, m colours.
  • A partial assignment on the first i vertices is legal iff every edge among those i is bichromatic.
  • Degree bound: \chi(G) \le \Delta(G)+1 (greedy colouring). Backtracking may still need to search; the bound only names a sufficient m.
  • 2-colouring: O(n+m_{\mathrm{edges}}) by BFS, not 2^n backtracking.

Exam traps & shortcuts

  • Colour vertices in a fixed order (say 0..n-1). Reordering can change the size of the tree, not the existence answer.
  • The clash test uses only already-coloured neighbours. A later neighbour is not a reason to reject a colour now.
  • Finding one colouring is search. Counting all colourings is a different, harder output. This topic stops at the first success unless a stem asks for a count.
  • Do not quote this search as a polynomial 3-colouring algorithm.

Reference tables

Edges AB, BC, CD, DA, AC. No BD.

Running graph
VertexNeighboursFirst-success colour
AB, C, D1
BA, C2
CA, B, D3
DA, C2

Recap

Night-before colouring-search pegs.

Search
Write an m-colouring. The NPC decision is a different topic.
Loop
Try c, reject if a neighbour holds c, recurse, unchoose.
Walk
A1 B2 C3 D2 on the triangle-plus-D. No edge BD.
m=2
BFS bipartite test, not this tree.

Practise Graph Colouring by Backtracking

Reading is free and needs no account. Practice, mocks and progress live in the app.

  • A 5-question practice set that ends the chapter
  • 4 quick checks with worked explanations
  • Timed mocks scored with the real marking scheme
  • Readiness tracked per topic, kept on your device
Continue with Google — freeNo card, no trial. Works offline once installed.