Skip to content

Commit eabd772

Browse files
committed
Bron–Kerbosch algorithm added.
1 parent 5e9d9f7 commit eabd772

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package com.thealgorithms.graph;
2+
3+
import java.util.ArrayList;
4+
import java.util.HashSet;
5+
import java.util.List;
6+
import java.util.Set;
7+
8+
/**
9+
* Implementation of the Bron–Kerbosch algorithm with pivoting for enumerating all maximal cliques
10+
* in an undirected graph.
11+
*
12+
* <p>The input graph is represented as an adjacency list where {@code adjacency.get(u)} returns the
13+
* set of vertices adjacent to {@code u}. The algorithm runs in time proportional to the number of
14+
* maximal cliques produced and is widely used for clique enumeration problems.</p>
15+
*
16+
* @author <a href="https://github.com/VictorFrench">Victor French</a>
17+
*/
18+
public final class BronKerbosch {
19+
20+
private BronKerbosch() {
21+
}
22+
23+
/**
24+
* Finds all maximal cliques of the provided graph.
25+
*
26+
* @param adjacency adjacency list where {@code adjacency.size()} equals the number of vertices
27+
* @return a list containing every maximal clique, each represented as a {@link Set} of vertices
28+
* @throws IllegalArgumentException if the adjacency list is {@code null}, contains {@code null}
29+
* entries, or references invalid vertices
30+
*/
31+
public static List<Set<Integer>> findMaximalCliques(List<Set<Integer>> adjacency) {
32+
if (adjacency == null) {
33+
throw new IllegalArgumentException("Adjacency list must not be null");
34+
}
35+
36+
int n = adjacency.size();
37+
List<Set<Integer>> graph = new ArrayList<>(n);
38+
for (int u = 0; u < n; u++) {
39+
Set<Integer> neighbors = adjacency.get(u);
40+
if (neighbors == null) {
41+
throw new IllegalArgumentException("Adjacency list must not contain null sets");
42+
}
43+
Set<Integer> copy = new HashSet<>();
44+
for (int v : neighbors) {
45+
if (v < 0 || v >= n) {
46+
throw new IllegalArgumentException("Neighbor index out of bounds: " + v);
47+
}
48+
if (v != u) {
49+
copy.add(v);
50+
}
51+
}
52+
graph.add(copy);
53+
}
54+
55+
Set<Integer> r = new HashSet<>();
56+
Set<Integer> p = new HashSet<>();
57+
Set<Integer> x = new HashSet<>();
58+
for (int v = 0; v < n; v++) {
59+
p.add(v);
60+
}
61+
62+
List<Set<Integer>> cliques = new ArrayList<>();
63+
bronKerboschPivot(r, p, x, graph, cliques);
64+
return cliques;
65+
}
66+
67+
private static void bronKerboschPivot(
68+
Set<Integer> r,
69+
Set<Integer> p,
70+
Set<Integer> x,
71+
List<Set<Integer>> graph,
72+
List<Set<Integer>> cliques) {
73+
if (p.isEmpty() && x.isEmpty()) {
74+
cliques.add(new HashSet<>(r));
75+
return;
76+
}
77+
78+
int pivot = choosePivot(p, x, graph);
79+
Set<Integer> candidates = new HashSet<>(p);
80+
if (pivot != -1) {
81+
candidates.removeAll(graph.get(pivot));
82+
}
83+
84+
for (Integer v : candidates) {
85+
r.add(v);
86+
Set<Integer> newP = intersection(p, graph.get(v));
87+
Set<Integer> newX = intersection(x, graph.get(v));
88+
bronKerboschPivot(r, newP, newX, graph, cliques);
89+
r.remove(v);
90+
p.remove(v);
91+
x.add(v);
92+
}
93+
}
94+
95+
private static int choosePivot(Set<Integer> p, Set<Integer> x, List<Set<Integer>> graph) {
96+
int pivot = -1;
97+
int maxDegree = -1;
98+
Set<Integer> union = new HashSet<>(p);
99+
union.addAll(x);
100+
for (Integer v : union) {
101+
int degree = graph.get(v).size();
102+
if (degree > maxDegree) {
103+
maxDegree = degree;
104+
pivot = v;
105+
}
106+
}
107+
return pivot;
108+
}
109+
110+
private static Set<Integer> intersection(Set<Integer> base, Set<Integer> neighbors) {
111+
Set<Integer> result = new HashSet<>();
112+
for (Integer v : base) {
113+
if (neighbors.contains(v)) {
114+
result.add(v);
115+
}
116+
}
117+
return result;
118+
}
119+
}

0 commit comments

Comments
 (0)