Maximum Clique

A clique is a set of pairwise adjacent vertices; an independent set is a set of pairwise non-adjacent vertices. They are the same problem on complementary graphs:

And minimum vertex cover is the complement of a maximum independent set:

All three are NP-hard in general.

The tractable cases

Graph classComplexity
BipartiteP — König: MVC = max matching, MIS = − max matching
TreeP — linear tree DP
Interval graphP — greedy by right endpoint
Chordal graphP — perfect elimination ordering
Perfect graphP (via SDP; impractical but polynomial)
Planarstill NP-hard, but has a PTAS
Bounded treewidthP — DP over a tree decomposition
GeneralNP-hard, inapproximable within

Check for bipartiteness first. A great many “select a maximum set with no two conflicting” problems are secretly bipartite matching.

Tree DP for maximum weight independent set

void dfs(int u, int p) {
    dp[u][0] = 0; dp[u][1] = w[u];
    for (int v : adj[u]) {
        if (v == p) continue;
        dfs(v, u);
        dp[u][0] += max(dp[v][0], dp[v][1]);
        dp[u][1] += dp[v][0];                          // v cannot be chosen
    }
}
// answer: max(dp[root][0], dp[root][1])

. See Tree DP.

Exact algorithms for general graphs

MethodTimeFeasible
Brute force over subsets20
Bron-Kerbosch with pivoting40-60
Bron-Kerbosch with bitsets, tiny constant100-150
Branch and bound with a colouring boundexponential, strong pruning100-1000 (sparse)
Meet in the middle40-50
Degeneracy-ordered Bron-Kerboschlarge sparse graphs

is the maximum possible number of maximal cliques (Moon-Moser), so Bron-Kerbosch is worst-case optimal for enumeration.

Meet in the middle for max independent set

Split the vertices into halves and ( each):

  1. Enumerate all independent subsets of .
  2. For each subset , compute the set of -vertices compatible with it (a bitmask AND).
  3. Precompute, for every subset of , the maximum-weight independent subset within it — an SOS-style DP over supersets.
  4. Combine.

— handles . See Meet in the Middle.

The colouring bound

The key pruning for branch and bound: greedily colour the candidate set; a clique within it cannot exceed the number of colours used.

// order candidates by greedy colouring; prune when
// current_clique_size + colours_remaining <= best

Cheap to compute, and far tighter than “candidate count”. It is what makes modern max-clique solvers handle graphs with hundreds of vertices.

Bitset representation

For , store each vertex’s neighbourhood as a bitset. Then is one AND, and iterating the candidates uses _Find_next:

bitset<128> adj[128];
bitset<128> newP = P & adj[v];                          // O(n/64)

This is a 64× speedup and is what turns Bron-Kerbosch from "" into "". See Bitset Optimization.

Approximation and hardness

ProblemBest knownHardness
Max clique inapproximable
Max independent setsamesame
Min vertex cover2no better than 1.36 (2 under UGC)
MIS on bounded-degree

Independent set is one of the hardest problems to approximate; vertex cover, its complement, is one of the easiest. The asymmetry comes from the objective: a 2-approximation for a small cover corresponds to a terrible approximation for the large complementary set.

Parameterized results

Vertex cover is FPT: for a cover of size , via branching on an uncovered edge plus kernelisation to vertices. Independent set (parameterized by solution size) is W[1]-hard — no FPT algorithm expected. See Parameterized Complexity.

Bron-Kerbosch

Purpose: Enumerate all maximal cliques of an undirected graph. With pivoting, it runs in — which is optimal, because a graph can have that many maximal cliques (Moon-Moser).

Algorithm

Recursive backtracking on three sets:

  • — the clique built so far,
  • — candidates that can still extend ,
  • — vertices already processed (used to avoid reporting the same clique twice).
BronKerbosch(R, P, X):
    if P and X are both empty:
        report R as a maximal clique
    choose a pivot u from P ∪ X maximising |P ∩ N(u)|
    for each v in P \ N(u):
        BronKerbosch(R ∪ {v}, P ∩ N(v), X ∩ N(v))
        P ← P \ {v}
        X ← X ∪ {v}

Why the pivot. Any maximal clique must contain either or a vertex not adjacent to . So it suffices to branch on , and choosing to maximise makes that set as small as possible. Without pivoting the algorithm still works but is dramatically slower.

Code

Bitset version — the one to use, since all set operations become single machine words:

int n;
vector<unsigned long long> adj;   // adj[v] = bitmask of neighbours (n <= 64)
vector<unsigned long long> cliques;
 
void bk(unsigned long long R, unsigned long long P, unsigned long long X) {
    if (!P && !X) { cliques.push_back(R); return; }
 
    // pivot: vertex of P|X with the most neighbours inside P
    int pivot = -1, best = -1;
    unsigned long long PX = P | X;
    for (unsigned long long t = PX; t; t &= t - 1) {
        int u = __builtin_ctzll(t);
        int c = __builtin_popcountll(P & adj[u]);
        if (c > best) { best = c; pivot = u; }
    }
 
    unsigned long long cand = P & ~adj[pivot];
    for (unsigned long long t = cand; t; t &= t - 1) {
        int v = __builtin_ctzll(t);
        bk(R | (1ULL << v), P & adj[v], X & adj[v]);
        P &= ~(1ULL << v);
        X |= (1ULL << v);
    }
}

Complexity

  • Time: worst case with pivoting — matching the maximum possible number of maximal cliques
  • With a degeneracy ordering at the top level: where is the graph degeneracy — near-linear on sparse real-world graphs
  • Space: for the adjacency bitsets, recursion depth

Variants / Use Cases

  • Maximum clique — take the largest reported clique, or use a dedicated branch-and-bound solver with a colouring bound (much faster when you only need the maximum)
  • Maximum independent set — run on the complement graph
  • Minimum vertex cover — minus the maximum independent set (König’s theorem gives a flow solution in bipartite graphs)
  • Graph colouring lower bounds — the clique number bounds the chromatic number from below
  • Community detection / social network analysis — the original motivation for degeneracy-ordered Bron-Kerbosch
  • Maximum Clique and Independent Set — the topic page