昨日老刘开了最大团专题后,起初以为挺简单,后来发现有点麻烦。能用的资料又很少。分享一下学习的东西
以poj 2989为例,题意是求 不同极大团的数量
要用Bron–Kerbosch算法
首先是最朴素的伪代码,没有任何剪枝(来自维基百科)https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm
BronKerbosch(All, Some, None): if Some and None are both empty: report All as a maximal clique for each vertex v in Some: BronKerbosch1(All ⋃ {v}, Some ⋂ N(v), None ⋂ N(v)) Some := Some \ {v} None := None ⋃ {v}
N(v)为顶点v相邻的点。
all为已取的顶点集,some为未处理顶点集(初始状态是全部顶点),none为不取的顶点集
最大团类型的题目中,我们求最大团顶点数时只要some,要求记录路径时要all和some,这里求极大团数量,需要all、some、none。
c代码:
void dfs(int d, int an, int sn, int nn)
//d为搜索深度,an、sn、nn分别为all、some、none集合中顶点数,
{
if(sn == 0 && nn == 0) ++ S;//sn==0搜索到终点,只有nn==0时,才是一个极大团,S为极大团数量
for(int i = 0; i < sn; i ++)
{
int v = some[d][i];
int tsn = 0, tnn = 0;
for(int j = 0; j < an; j ++) all[d + 1][j] = all[d][j];
all[d + 1][an] = v;
for(int j = 0; j < sn; j ++)if(g[v][some[d][j]]) some[d + 1][tsn ++] = some[d][j];
for(int j = 0; j < nn; j ++) if(g[v][none[d][j]]) none[d + 1][tnn ++] = none[d][j];
dfs(d + 1, an + 1, tsn, tnn);
//把v从some取出,放入none
some[d][i] = 0, none[d][nn ++] = v;
}
}
(
原文:
The basic form of the algorithm, described above, is inefficien