最大團定義:即為最大完全子圖。
給定無向圖G=(V,E)。如果U是V的一個子集,且對任意u,v屬於U 有(u,v)屬於E,則稱U 是G 的完全子圖。
G 的完全子圖U是G的團當且僅當U不包含在G 的更大的完全子圖中,即U就是最大完全子圖。
G 的最大團是指G中所含頂點數最多的團。
最大獨立集定義:
獨立集是指圖 G 中兩兩互不相鄰的頂點構成的集合。
當且僅當對於U 中任意點u 和v所構成的邊(u , v) 不是G 的一條邊時,U 定義了一個空子圖。
當且僅當一個子集不被包含在一個更大的點集中時,該點集是圖G 的一個獨立集(independent set ),同時它也定義了圖G 的空子圖。
最大獨立集是具有最大尺寸的獨立集。
對於不同圖而言,我們有以下結論:
1、對於一般圖而言: 原圖的最大獨立集 = 補圖的最大團
2、對於二部圖而言: 最大獨立集 = 點數 - 最小點覆蓋(最大匹配數)
一、對於一般圖,圖的最大團(最大獨立集)問題是一個NP問題,因此我們可以采用搜索的方式求解問題。
例題:Graph Coloring
此題需要我們求解圖的最大獨立集,我們只需要求出補圖的最大團即可(此處用的是求最大團的dfs模板,如果采用的原圖建圖求出來的就是最大團)
點擊查看折疊代碼塊
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 510;
int n,m;
bool cmp(char x[],char y[]){
int cnt = 0;
int len = strlen(x);
for(int i = 0;i<len;++i){
if(x[i]!=y[i])cnt++;
}
if(cnt>2)return true;
else return false;
}
int T;
int bestx[maxn],x[maxn];
int ans,cnt = 0;
int g[maxn][maxn];
bool place(int t){
bool ok = 1;
for (int j=1;j<t;j++){
if(x[j] && !g[t][j]){
ok = 0;
break;
}
}
return ok;
}
void dfs(int t){
if(t>n){
for (int i=1;i<=n;i++){
bestx[i] = x[i];
}
ans=cnt;
return ;
}
if(place(t)){
x[t] = 1;
cnt++;
dfs(t+1);
cnt--;
x[t] = 0;
}
if(cnt+n-t>ans){
x[t] = 0;
dfs(t+1);
}
}
int main(){
cin>>T;
while(T--){
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++){
x[i] = 0;
for (int j=1;j<=n;j++){
g[i][j] = 1;
}
}
cnt = 0,ans = 0;
for (int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
g[u][v] = g[v][u] = 0;//這里建的是補圖
}
dfs(1);
printf("%d\n",ans);
int ct = 0;
for (int i=1;i<=n;i++){
if(bestx[i]){
printf("%d",i);
printf("%c",ct==ans?'\n':' ');
ct++;
}
}
}
return 0;
}