POJ 2989 Bron-Kerbosch算法 极大团数量

题意:给出n个人,其中m对朋友,求极大团数量(若超过1000则输出“Too many maximal sets of friends.”)。

思路:

1)定义:一个点集S被称为极大团,当且仅当S中的所有点均互为朋友,且所有不在S中的人,均与S中的某些人不是朋友。

2)算法:Bron-Kerbosch算法(DFS)

wiki上的伪代码,其中All是已经选的点集,Some是还未选的,None是已经搜过的(避免重复,其实就是不能选的)

N(v)指与v的朋友(相邻点)

   BronKerbosch(All, Some, None):
       if Some and None are both empty:
           report All as a maximal clique //所有点已选完,且没有不能选的点,累加答案
       for each vertex v in Some: //枚举Some中的每一个元素
           BronKerbosch1(All ⋃ {v}, Some ⋂ N(v), None ⋂ N(v)) 
           //将v加入All,显然只有与v为朋友的人才能作为备选,None中也只有与v为朋友的才会对接下来造成影响
           Some := Some - {v} //已经搜过,在Some中删除,加入None
           None := None ⋃ {v}
3)小优化:

设key = some[1],则仅当key与v不为朋友时,才需要枚举v,因为此时与v相关的必定已被搜过(与None同理,但可以大大加速)

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <cstring>
#define For(i,j,k) for(int i = j;i <= (int)k;i ++)
#define Set(i,j) memset(i, j, sizeof(i))

using namespace std;
const int N = 130;
int Ans, G[N][N], all[N][N], some[N][N], none[N][N];

void DFS(int n, int an, int sn, int nn){
	if(!sn && !nn) Ans++;
	if(Ans > 1000) return;
	int key = some[n][1];
	For(j,1,sn){
		int v = some[n][j], tsn = 0, tnn = 0;
		if(G[key][v])continue;
		For(i,1,an) all[n+1][i] = all[n][i]; all[n+1][an+1] = v;
		For(i,1,sn) if(G[v][some[n][i]]) some[n+1][++tsn] = some[n][i];
		For(i,1,nn) if(G[v][none[n][i]]) none[n+1][++tnn] = none[n][i];
		DFS(n + 1, an + 1, tsn, tnn);
		some[n][j] = 0, none[n][++nn] = v;
	}
}

int main(){
	int n, m;
	while(scanf("%d%d", &n, &m) == 2){
		int x, y;
		Set(G, 0), Ans = 0;
		For(i,1,m){
			scanf("%d%d", &x, &y);
			G[x][y] = G[y][x] = 1;
		}
		For(i,1,n) some[1][i] = i;
		DFS(1, 0, n, 0);
		if(Ans > 1000) puts("Too many maximal sets of friends.");
		else printf("%d\n", Ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值