最大獨立集 最大團

最大團就是一個無向圖中找到一個點集,這集合中的任意兩個點直接都有邊直接相連,點數最大的點集就是最大團。
最大獨立集就是一個集合中的任意兩個點之間都沒有邊相連接,最大的點集就是最大獨立集。
圖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(顯而易見)

I. Error Correction

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章