极大团(maximal clique)算法:Born_kerbosch算法

 

不了解极大团(maximal clique)的,请看极大团这篇文章

参考资料:

Bron_Kerbosch算法

团、极大团、最大团介绍

当给出一个图后,我们应该怎么去寻找其中的极大子团呢?

寻找极大子团的最简单的思想是:

1.生成原始图的所有子图(可能的子图有2*n个,n代表顶点个数)

2.判断这些子图是不是团

3.将不是极大团的团删除

 

Born_Kerbosch算法

这个算法主要构造三个集合:

R集合:存储当前极大团中加入的顶点

P集合:存储可能还加入的点

X集合:存储的是已经假如过某个极大团的点(作用是判重,因为会从每个顶点开始,枚举所有团,如果不对已经加入到某个极大团的顶点进行标记,可能会有重复极大团的出现)

 

基础Born_kerbosch算法

1.对于任意一个在集合P中的顶点V,我们把V加入到R集合(集合P中的每一个顶点均与R集合中所有的点是连接的,所以加入顶点V后,依然能保证集合R是个团),然后对在P集合中且与V相连的这部分点中,寻找下一个可能加入到R集合的点。(意思就时加入点v至R集合后更新P集合,使P集合中的任意一个点依然能和R集合中每一个点都是连接的。因为这里新R集合中加入了V,所以只要是原p集合中且与v顶点相连的这些顶点就是与新R集合中所有顶点相连)

2.回溯时把顶点V从P中移除并加入到X集合,表示在当前状态下包含顶点V的极大团已经计算完毕。

3.R集合为极大团时,必须满足P与X都是空的。P存放的是还可能加入到极大团R中的点,P集合为空表示已经没有点能加入到R中了。而X中存放的是已经完成极大团计算的点,且X集合中的任意一个点必然是与R中每个顶点都连接(因为我们每次向下dfs时,还对P和X分别进行取与R集合内都连接的操作来保证,而且X中的点就是从R中取出的点,当然会和R集合中的每个点都连接),即X中的点必然可以和R集合构成极大团。如果X集合不为空的话,可以把X的点加入到R集合中从而构成一个团R1,R1的顶点数大于R,说明R就不是一个极大团,R1集合中的极大团是之前计算包含x集合中的点的极大团的时候计算过了的,故当且仅当P、X集合都为空时R才是一个极大团。

算法图例

 

Born_Kerbosch算法的优化

在上面这个方法中,我们进行了许多不必要的判断,例如在我们找到了极大团{1、2、3}之后,依然去对{1、3},{2、3},{3}这些团进行了判断,然而这些显然不是极大团。所以现在考虑的是对其进行优化,使程序不用进行不必要的递归。
当我们将一个结点u,放入到R集合后,再取下一个结点,取的必然是u的邻居结点(因为再更新P和X时,会将不是邻居结点的结点都过滤掉)。通俗的讲就是如果取完u之后我们再取与u相邻的点v也能加入到极大团,那么我们只取u就好了,因为我们由u开始递归,已经找到了u及其邻居结点v等等结点构成的极大团了,没有必要再去从v开始寻找极大团,这会增加不必要的计算。至于v可能可以其他结点构成另一个极大团,如果这个极大团包括了u,那么由u开始就已经找到了这个极大团了;如果这个极大团不包括u,那说明这个极大团里面一定存在和u结点不相连的结点k,那没必要从v开始寻找这个极大团了,从u的非邻居结点k开始,一样可以找到这个极大团。这样对u及其邻居结点构成的极大团,只需要从u开始寻找一次就可以了,接下来就直接从u的非邻居结点k开始寻找极大团,这样可以减少许多不必要的计算。

 

posted @ 2020-03-16 08:44  持&恒  阅读(166)  评论(0编辑  收藏