package com.thealgorithms.graph; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Implementation of the Bron–Kerbosch algorithm with pivoting for enumerating all maximal cliques * in an undirected graph. * *

The input graph is represented as an adjacency list where {@code adjacency.get(u)} returns the * set of vertices adjacent to {@code u}. The algorithm runs in time proportional to the number of * maximal cliques produced and is widely used for clique enumeration problems.

* * @author Wikipedia: Bron–Kerbosch algorithm */ public final class BronKerbosch { private BronKerbosch() { } /** * Finds all maximal cliques of the provided graph. * * @param adjacency adjacency list where {@code adjacency.size()} equals the number of vertices * @return a list containing every maximal clique, each represented as a {@link Set} of vertices * @throws IllegalArgumentException if the adjacency list is {@code null}, contains {@code null} * entries, or references invalid vertices */ public static List> findMaximalCliques(List> adjacency) { if (adjacency == null) { throw new IllegalArgumentException("Adjacency list must not be null"); } int n = adjacency.size(); List> graph = new ArrayList<>(n); for (int u = 0; u < n; u++) { Set neighbors = adjacency.get(u); if (neighbors == null) { throw new IllegalArgumentException("Adjacency list must not contain null sets"); } Set copy = new HashSet<>(); for (int v : neighbors) { if (v < 0 || v >= n) { throw new IllegalArgumentException("Neighbor index out of bounds: " + v); } if (v != u) { copy.add(v); } } graph.add(copy); } Set r = new HashSet<>(); Set p = new HashSet<>(); Set x = new HashSet<>(); for (int v = 0; v < n; v++) { p.add(v); } List> cliques = new ArrayList<>(); bronKerboschPivot(r, p, x, graph, cliques); return cliques; } private static void bronKerboschPivot(Set r, Set p, Set x, List> graph, List> cliques) { if (p.isEmpty() && x.isEmpty()) { cliques.add(new HashSet<>(r)); return; } int pivot = choosePivot(p, x, graph); Set candidates = new HashSet<>(p); if (pivot != -1) { candidates.removeAll(graph.get(pivot)); } for (Integer v : candidates) { r.add(v); Set newP = intersection(p, graph.get(v)); Set newX = intersection(x, graph.get(v)); bronKerboschPivot(r, newP, newX, graph, cliques); r.remove(v); p.remove(v); x.add(v); } } private static int choosePivot(Set p, Set x, List> graph) { int pivot = -1; int maxDegree = -1; Set union = new HashSet<>(p); union.addAll(x); for (Integer v : union) { int degree = graph.get(v).size(); if (degree > maxDegree) { maxDegree = degree; pivot = v; } } return pivot; } private static Set intersection(Set base, Set neighbors) { Set result = new HashSet<>(); for (Integer v : base) { if (neighbors.contains(v)) { result.add(v); } } return result; } }