最大团:从无向图的顶点集中选出k个并且k个顶点之间任意两点之间都相邻(完全图),最大的k就是最大团
最大独立集:从无向图中的顶点中选出k个并且k个顶点之间互不相邻,最大的k就是最大独立集
性质:无向图的最大团==该无向图补图的最大独立集,无向图的最大独立集==该无向图补图的最大团
算法实现:应用递推+dfs
令Si={vi,v(i+1),...,vn},用mc[i]表示MC(Si)。倒着算mc[i],那么显然MC(V)=mc[1]。此外有mc[i]=mc[i+1]/mc[i]=mc[i+1]+1,且后一种情况发生的唯一可能是在Si中找到一个包含Vi的团,所以只要搜是不是在Si中存在一个包含Vi且比当前最大团还大的团。
dfs的两个剪枝:
1)current_size+remain_vertex>ans
2)current_size+mc[i]>ans
附上代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=55;
int n;
bool g[maxn][maxn];
bool found;
int len[maxn],list[maxn][maxn],ans,mc[maxn];
void dfs(int size)
{
if(len[size]==0){
if(size>ans){
ans=size;
found=true;
}
}
for(int k=0;k<len[size]&&!found;k++){
if(size+len[size]-k<=ans){
break;
}
int i=list[size][k];
if(size+mc[i]<=ans){
break;
}
len[size+1]=0;
for(int j=k+1;j<len[size];j++){
if(g[i][list[size][j]]){
list[size+1][len[size+1]++]=list[size][j];
}
}
dfs(size+1);
}
}
void max_cluster()
{
mc[n]=ans=1;
for(int i=n-1;i;i--){
found=false;
len[1]=0;
for(int j=i+1;j<=n;j++){
if(g[i][j]){
list[1][len[1]++]=j;
}
}
dfs(1);
mc[i]=ans;
}
}
int main()
{
while(scanf("%d",&n)!=EOF&&n){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&g[i][j]);
}
}
max_cluster();
printf("%d\n",ans);
}
return 0;
}