最大团就是一个无向图中找到一个点集,这集合中的任意两个点直接都有边直接相连,点数最大的点集就是最大团。
最大独立集就是一个集合中的任意两个点之间都没有边相连接,最大的点集就是最大独立集。
图G的最大独立集点数就是图G的补图Gv的最大团。
Bron-Kerbosch 算法求最大团,本质上就是爆搜加剪枝,最多能跑100的稠密图和1000左右甚至上万的稀疏图。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX_N=1010;
int n,m;
bool G[MAX_N][MAX_N];
int cnt[MAX_N];//cnt[i]为>=i的最大团点数
int group[MAX_N];//最大团的点
int vis[MAX_N];//记录点的位置
int res;//最大团的数目
bool dfs(int pos,int num){//num为当前独立集中的点数
int i,j;
for(i=pos+1;i<=n;i++){
if(cnt[i]+num<=res)//剪枝,若取i但cnt[i]+已经取了的点数仍<ans
return false;
if(G[pos][i]){//与当前团中元素比较,取Non-N(i)
for(j=0;j<num;j++)
if(!G[i][vis[j]])break;
if(j==num){//若为空,则皆与i相邻,则此时将i加入到最大团中
vis[num]=i;
if(dfs(i,num+1))
return true;
}
}
}
if(num>res){//每添加一个点最多使最大团数+1,后面的搜索就没有意义了
for(int i=0;i<num;i++)//最大团的元素
group[i]=vis[i];
res=num;//最大团中点的数目
return true;
}
return false;
}
void maxClique(){
res=-1;
for(int i=n;i>0;i--){//枚举所有点
vis[0]=i;
dfs(i,1);
cnt[i]=res;
}
}
//res为最大团点数
//group存的最大团的点,从0到res-1
/*for(i=1;i<=n;i++){//建补图代码!!
for(j=1;j<=n;j++){
if(i==j)
G[i][j]=false;
else
G[i][j]^=1;
}
}*/
二分图最小点覆盖就是最小的点数使得二分图的任何一条边的两个端点至少有一个被选中,即去掉最少的点使得剩余任意两点之间没有连边。
二分图最小点覆盖就是二分图最大匹配(匈牙利算法即可)。
二分图最大独立集,就是n-二分图最小点覆盖。
二分图最大团最大就是2(显而易见)
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int MAX_N=510;
char s[MAX_N][30];
int len;
int a[30];
vector<int>v[MAX_N];
bool check(int x,int y){
int i,j;
int cnt=0;
for(i=0;i<len;i++){
if(s[x][i]!=s[y][i]){
a[++cnt]=i;
}
}
if(cnt!=2)
return false;
if(s[x][a[1]]==s[y][a[2]]&&s[x][a[2]]==s[y][a[1]])
return true;
else
return false;
}
int col[MAX_N];
int match[MAX_N];
bool vis[MAX_N];
bool dfs(int x){
int i;
for(i=0;i<v[x].size();i++){
int y=v[x][i];
if(vis[y])
continue;
vis[y]=true;
if(!match[y]||dfs(match[y])){
match[y]=x;
return true;
}
}
return false;
}
void dfs1(int x){
for(int i=0;i<v[x].size();i++){
int y=v[x][i];
if(vis[y])
continue;
vis[y]=true;
col[y]=col[x]^1;
dfs1(y);
}
}
int main(void){
int n,i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%s",s[i]);
len=strlen(s[1]);
for(i=1;i<=n;i++){
for(j=i+1;j<=n;j++){
if(check(i,j)){
v[i].push_back(j);
v[j].push_back(i);
}
}
}
for(i=1;i<=n;i++){
if(vis[i])
continue;
col[i]=1;
vis[i]=true;
dfs1(i);
}
int res=0;
for(i=1;i<=n;i++){
//cout<<col[i]<<" "<<i<<"\n";
memset(vis,0,sizeof(vis));
if(col[i]==1&&dfs(i))
res++;
}
printf("%d\n",n-res);
return 0;
}