( 图论专题 )【最大团 】
最大团是什么:通俗点讲就是在一个无向图中找出一个点数最多的完全图。
当 G′ 是图 G 的子图,且 G′ 是关于 V′ 的完全图时,子图 G' 为图 G 的团;当 G' 是团,且不是其他团的子集时,G' 为图 G 的极大团;当 G' 是极大团时,且点数最多,G' 为图 G 最大团
当 G′ 中所有点不相邻,最大点集最大的图 G′ 为图 G 的最大独立集,且最大独立集数=补图的最大团
当用个数最少的团覆盖图 G 所有的点时,称为最小团覆盖,由于每个团中最多取一个点,因此有最大独立集<=最小团覆盖
简单来说,极大团是增加任一顶点都不再符合定义的团,最大团是图中含顶点数最多的极大团,最大独立集是除去图中的团后的点集,而最大团问题就是在一个无向图中找出一个点数最多的完全图。
对于弦图来说,求最大团一般使用 MCS 算法,而对于一般图来说,常使用 Bron-Kerbosch 算法
关于弦图的最大团:点击这里
Bron-Kerbosch 算法
Bron-Kerbosch 算法用于计算图中的最大的全连通分量,即计算图的最大团。
#include <bits/stdc++.h>
using namespace std;
int mp[105][105];
int len[1005],mc[1005],res,lis[105][105];
bool found;
int n;
void dfs(int sz){
int i, j, k;
if(len[sz] == 0){
if(sz > res){
res = sz;
found = true;
}
return;
}
for(k = 0; k < len[sz] && !found; ++k){
if(sz + len[sz] - k <= res){
break;
}
i = lis[sz][k];
if(sz + mc[i] <= res)break;
for(j = k + 1,len[sz+1]=0; j < len[sz]; ++j){
if(mp[i][lis[sz][j]]){
lis[sz+1][len[sz+1]++] = lis[sz][j];
}
}
dfs(sz+1);
}
}
void max_tuan(){
int i, j;
mc[n] = res = 1;
for(i = n-1;i;--i){
found=false;
len[1] = 0;
for(j = i+1; j <= n; j++){
if(mp[i][j]){
lis[1][len[1]++] = j;
}
}
dfs(1);
mc[i] = res;
}
}
int main()
{
cin>>n>>m;
for ( int i=0; i<m; i++ ) {
int u,v;cin>>u>>v;
mp[u][v] = mp[v][u] = 1;
}
max_tuan();
cout << res << endl;
return 0;
}