这里有几个概念要清楚:
最大团: V中取K个顶点,两点间相互连接
最大独立集: V中取K个顶点,两点间不连接
最大团数量 = 补图中最大独立集数,最大独立集数=补图中最大团数量
第一个回溯板子,,一般没啥用
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1000;
bool g[N][N];
bool x[N];
int cnt, bestn;
int n, e;
void backtrack(int v) {
if (v > n) {
bestn = cnt;
cout << "最大团数:" << bestn << endl;
for (int i = 1; i <= n; i++) {
if (x[i]) cout << i << " ";
}
cout << endl;
return;
}
int ok = true;
for (int i = 1; i < v; i++) {
if (x[i] && !g[i][v]) {
ok = false;
break;
}
}
if (ok) {
cnt++;
x[v] = true;
backtrack(v + 1);
cnt--;
}
if (cnt + n - v > bestn) {
x[v] = false;
backtrack(v + 1);
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cin >> n >> e;
int u, v;
for (int i = 1; i <= e; i++) {
cin >> u >> v;
g[u][v] = g[v][u] = true;
}
backtrack(1);
return 0;
}
/*
5 7
1 2
1 4
1 5
2 5
2 3
3 5
4 5
*/
第二个Bron-Kerbosch板子,常用
省略了建图部分
AC代码:
#include<cstdio>
#include<cstring>
#define N 1010
bool flag[N], a[N][N];
int ans, cnt[N], group[N], n, vis[N];
// 最大团: V中取K个顶点,两点间相互连接
// 最大独立集: V中取K个顶点,两点间不连接
// 最大团数量 = 补图中最大独立集数
bool dfs( int u, int pos ){
int i, j;
for( i = u+1; i <= n; i++){
if( cnt[i]+pos <= ans ) return 0;
if( a[u][i] ){
// 与目前团中元素比较,取 Non-N(i)
for( j = 0; j < pos; j++ ) if( !a[i][ vis[j] ] ) break;
if( j == pos ){ // 若为空,则皆与 i 相邻,则此时将i加入到 最大团中
vis[pos] = i;
if( dfs( i, pos+1 ) ) return 1;
}
}
}
if( pos > ans ){
for( i = 0; i < pos; i++ )
group[i] = vis[i]; // 最大团 元素
ans = pos;
return 1;
}
return 0;
}
void maxclique()
{
ans=-1;
for(int i=n;i>0;i--)
{
vis[0]=i;
dfs(i,1);
cnt[i]=ans;
}
}```
模板题1:[https://acm.hdu.edu.cn/showproblem.php?pid=1530](https://acm.hdu.edu.cn/showproblem.php?pid=1530)
```cpp
#include <iostream>
#include <stdio.h>
using namespace std;
const int N = 100;
int g[N][N]; //图
int cnt[N]; //记录以各个点出发的最大团
int group[N],vis[N];
int ans,n;
int dfs(int v,int pos){
int i,j;
for(i = v+1;i<=n;i++){
if(cnt[i] + pos <= ans) return 0;
if(g[v][i]){
for(j = 0;j<pos;j++) if(!g[i][vis[j]]) break;
if(j == pos){
vis[pos] = i;
if(dfs(i,pos+1)) return 1;
}
}
}
if(pos > ans){
ans = pos;
for(int i = 0;i<pos;i++){
group[i] = vis[i];
}
return 1;
}
return 0;
}
void maxClique(){
ans = -1;
for(int i = n;i>0;i--){
vis[0] = i;
dfs(i,1);
cnt[i] = ans;
}
}
int main(){
while(scanf("%d",&n)&&n){
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
scanf("%d",&g[i][j]);
}
}
maxClique();
cout << ans << endl;
}
return 0;
}
模板题2:http://poj.org/problem?id=1419
AC代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int N = 110;
int g[N][N];
int cnt[N];
int group[N],vis[N];
int ans,n,m;
int dfs(int u, int pos){
int i,j;
for(i = u+1;i<=n;i++){
if(cnt[i] + pos <= ans) return 0;
for(j = 0;j<pos;j++) if(!g[i][vis[j]]) break;
if(j == pos){
vis[pos] = i;
if(dfs(i,pos+1)) return 1;
}
}
if(pos > ans){
for(i = 0;i<pos;i++) group[i] = vis[i];
ans = pos;
return 1;
}
return 0;
}
void maxClique(){
ans = -1;
for(int i = n;i>0;i--){
vis[0] = i;
dfs(i,1);
cnt[i] = ans;
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(g,0,sizeof(g));
cin >> n >> m;
int u,v;
for(int i = 1;i<=m;i++){
scanf("%d%d",&u,&v);
g[u][v] = g[v][u] = 1;
}
//建成补图
for(int i = 1;i<=n;i++)
for(int j = 1;j<=n;j++){
if(i != j) g[i][j] ^=1;
}
maxClique();
if(ans == 0){
printf("%d\n\n",ans);
continue;
}
printf("%d\n",ans);
for(int i = 0;i<ans;i++)
printf("%d%c",group[i]," \n"[i+1==ans]);
}
return 0;
}