You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

67 lines
1.9 KiB
Java

5 years ago
import java.util.*;
// https://en.wikipedia.org/wiki/BronKerbosch_algorithm
public class BronKerbosh {
public static int BronKerbosch(long[] g, long cur, long allowed, long forbidden, int[] weights) {
if (allowed == 0 && forbidden == 0) {
int res = 0;
for (int u = Long.numberOfTrailingZeros(cur); u < g.length; u += Long.numberOfTrailingZeros(cur >> (u + 1)) + 1)
res += weights[u];
return res;
}
if (allowed == 0)
return -1;
int res = -1;
int pivot = Long.numberOfTrailingZeros(allowed | forbidden);
long z = allowed & ~g[pivot];
for (int u = Long.numberOfTrailingZeros(z); u < g.length; u += Long.numberOfTrailingZeros(z >> (u + 1)) + 1) {
res = Math.max(res, BronKerbosch(g, cur | (1L << u), allowed & g[u], forbidden & g[u], weights));
allowed ^= 1L << u;
forbidden |= 1L << u;
}
return res;
}
// random test
public static void main(String[] args) {
Random rnd = new Random(1);
for (int step = 0; step < 1000; step++) {
int n = rnd.nextInt(16) + 1;
long[] g = new long[n];
int[] weights = new int[n];
for (int i = 0; i < n; i++)
weights[i] = rnd.nextInt(1000);
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
if (rnd.nextBoolean()) {
g[i] |= 1L << j;
g[j] |= 1L << i;
}
int res1 = BronKerbosch(g, 0, (1L << n) - 1, 0, weights);
int res2 = maxCliqueSlow(g, weights);
if (res1 != res2)
throw new RuntimeException();
}
}
static int maxCliqueSlow(long[] g, int[] weights) {
int res = 0;
int n = g.length;
for (int set = 0; set < 1 << n; set++) {
boolean ok = true;
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
ok &= (set & (1 << i)) == 0 || (set & (1 << j)) == 0 || (g[i] & (1L << j)) != 0;
if (ok) {
int cur = 0;
for (int i = 0; i < n; i++)
if ((set & (1 << i)) != 0)
cur += weights[i];
res = Math.max(res, cur);
}
}
return res;
}
}