图论学习——最大团与最大独立集
最大团定义:即为最大完全子图。
给定无向图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;
}