最近注意到了图论中的最大团问题。最大团问题是一个 NP 完全问题,在此对它做简单介绍,并介绍具有代表性的 Bron-Kerbsch 算法。
什么是一个团?
最大团问题首先一个图的问题,假设读者已经知道图的概念。
假设一个无向图
,一个
团是图
的子图,该子图中的所有顶点之间都有边将它们相连。
极大团指的是,该团不包含于图
的任何其他团,即不是任何其他团的真子集。
最大团指的是结点数量最多的极大团。
最大团问题的 Bron-Kerbosch 算法
对于一个无向图,找到其最大团是 NP 完全问题。本文介绍最大团问题的 Bron-Kerbosch 算法。
Bron–Kerbosch 算法是由荷兰科学家 Coenraad Bron 和 Joep Kerbosch 设计的,他们于1973年发表了论文《Algorithm 457: finding all cliques of an undirected graph》。理论上,在输入更少的最大独立子集时,算法运行时间最短。Bron–Kerbosch 算法和后续算法通常被认为在实践中比其他算法更加有效。
Akkoyunlu(1973)在同时代提出的算法虽然用不同的术语表示,但由于它生成相同的递归搜索树,因此可以看作与 Bron-Kerbosch 算法相同。
无枢轴算法
Bron–Kerbosch 算法的基本形式是一种递归回溯算法,用于搜索给定图
的所有极大团。
总体上,给定三个不相交的顶点集
,它找到包含
中的所有顶点、
中的某些顶点和不在
中的顶点的极大团。在算法的每次调用中,
和
是不相交的集合,它们的并集由添加到
时会形成团的那些顶点组成。换句话说,
是连接到
的每个元素的一组顶点。当
和
都为空时,没有其他元素可以添加到
,因此
是最大团,算法输出
。
在开始递归算法前,将
和
设置为空集,将
设置为图的顶点集。在每个递归调用中,算法依次考虑
中的顶点。如果没有这样的顶点,分为两种情况:如果
为空,将
报告为最大团;如果
并不为空,进行回溯。对于从
中选择的每个顶点
,它将进行递归调用,其中将
添加到
中,并且将
和
限制为
的邻居集
,这将查找并报告
中包含
的所有团扩展。然后,它将
从
移到
,以在以后的团中将其排除在外,并继续使用
中的下一个顶点。
该算法可以写作以下伪代码形式:
R := {}
P := node set of G
X := {}
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}
关于算法原理,谈一些个人理解。算法开始时,
是空集,
是顶点集;算法结束时,
是最大团,
是空集。搜索最大团的过程就是顶点
从集合
移动到集合
的过程。
采用回溯策略的原因是,我们并不知道某个顶点
最终是否是最大团中的成员。如果递归算法选择
作为最大团的成员时,并没有找到最大团,那么应该回溯,并查找最大团中没有
的解。
在递归的过程中,
最终要形成一个最大团,
的元素就是递归过程中当前找到的最大团的组成元素。
是最大团的候选顶点集合,
不断地去掉递归完成的顶点
,在递归时取只在
中的元素,因为最大团中的每个顶点之间是互相连接的,要找到的最大团的下一个顶点,一定是
的邻接顶点。类似地,
是回溯过程中被放弃的顶点的集合,递归过程中每次也只需关注
的部分。
该算法还有很多后续改进的研究,如果学习到将补充在这里。