POJ3692 Kindergarten

题意

有G个女孩和B个男孩,男生互相认识,女生也互相认识,有M对男生认识女生,现要选出最多的人并且互相认识。

1 ≤ GB ≤ 200,0 ≤ M ≤ G × B

题解

但是我们发现,男孩之间都互相认识,女孩之间也互相认识,这样不能划分点集的。 但是男孩之间都互相认识,女孩之间也互相认识,所以男孩和男孩,女孩和女孩之间不存在不认识关系 如果以不认识作为边的话,认识不连边,这样就能划开点集。

那么我们求最大独立集(任意两点之间没有连边)即可。

最大独立集=点数-最大匹配数

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;

const int maxn=405;
int n,m,q,timer;
int match[maxn],vis[maxn];
bool connect[maxn][maxn];
vector<int> e[maxn];

void init(){
  memset(match,0,sizeof(match));
  memset(vis,0,sizeof(vis));
  memset(connect,false,sizeof(connect));
  for(int i=1;i<=n;i++) e[i].clear();
  timer=0;
}

bool dfs(int u){
  if(vis[u]==timer) return false;
  vis[u]=timer;
  for(unsigned int i=0;i<e[u].size();i++){
    int v=e[u][i];
    if(!match[v]||dfs(match[v])){
      match[v]=u;
      return true;
    }
  }
  return false;
}

int main(){
  int tot=0;
  while(tot++,scanf("%d%d%d",&n,&m,&q),n){
    init();
    for(int i=1;i<=q;i++){
      int x,y;
      scanf("%d%d",&x,&y);
      y+=n;
      connect[x][y]=true;
    }
    for(int i=1;i<=n;i++)
     for(int j=n+1;j<=n+m;j++)
      if(!connect[i][j]) e[i].push_back(j);
    int ans=0;
    for(int i=1;i<=n;i++){
      timer++;
      if(dfs(i)) ans++;
    }
    printf("Case %d: %d
",tot,n+m-ans);
  }
}
View Code
原文地址:https://www.cnblogs.com/sto324/p/11321943.html