总的来看,就是每次从集合 P 中取 vi 后,再从 P∩Nvi集合中取相邻结点,保证集合 R 中任意顶点间都两两相邻
1 2 3 4 5 6 7
BronKerbosch1(R,P,X): if P and X are both empty: report R as a maximal clique for each vertex v in P: BronKerbosch1(R ⋃ {v}, P ⋂ N(v), X ⋂ N(v)) P := P \ {v} X := X ⋃ {v}
由于对于任意的最大团,其必须包括顶点u 或 N−Nu,不然其必然需要通过添加它们来进行扩充,这显然矛盾,所以仅需测试顶点 u 以及 N−Nu 即可。
1 2 3 4 5 6 7 8
BronKerbosch2(R,P,X): if P and X are both empty: report R as a maximal clique choose a pivot vertex u in P ⋃ X for each vertex v in P \ N(u): BronKerbosch2(R ⋃ {v}, P ⋂ N(v), X ⋂ N(v)) P := P \ {v} X := X ⋃ {v}
BronKerbosch3(G): P = V(G) R = X = empty for each vertex v in a degeneracy ordering of G: BronKerbosch2(R ⋃ {v}, P ⋂ N(v), X ⋂ N(v)) P := P \ {v} X := X ⋃ {v}
int n, m; int G[N][N]; int group[N], vis[N], res, cnt[N];
boolgao(int u, int _cnt){ for (int i = u + 1; i <= n; ++i) { if (cnt[i] + _cnt <= res) { returnfalse; } if (G[u][i]) { bool F = true; for (int j = 0; j < _cnt; ++j) { if (!G[i][vis[j]]) { F = false; break; } } if (!F) continue; vis[_cnt] = i; if (gao(i, _cnt + 1)) { returntrue; } } } if (_cnt > res) { for (int i = 0; i < _cnt; ++i) { group[i] = vis[i]; } res = _cnt; returntrue; } returnfalse; }
voidmaxclique(){ res = -1; for (int i = n; i >= 1; --i) { vis[0] = i; gao(i, 1); cnt[i] = res; } }
intmain(){ int T; scanf("%d", &T); while (T--) { scanf("%d %d", &n, &m); memset(G, 0, sizeof G); for (int i = 1, u, v; i <= m; ++i) { scanf("%d %d", &u, &v); G[u][v] = G[v][u] = 1; } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { if (i == j) { G[i][j] = 0; } else { G[i][j] ^= 1; } } } maxclique(); if (res < 0) res = 0; printf("%d\n", res); for (int i = 0; i < res; ++i) { printf("%d ", group[i]); } putchar(10); } return0; }