http://acm.hdu.edu.cn/showproblem.php?pid=2444
题意:把学生分为两组,每组内的学生互相不认识,如果不能分成这样的两组,直接输出”No“;否则,从A组和B组中各选一个学生,放到一个寝室内(这两个学生必须相互认识),求最大能分几个寝室
分析:即判断是否形成二分图(黑白染色法)+二分图匹配。
黑白染色法:http://write.blog.csdn.net/postedit/17657591
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int NM=205;
int a[NM][NM],col[NM],link[NM],n;
bool f[NM];
bool Color(){
int i,j,t;
memset(col,-1,sizeof(col));
for(i=1;i<=n;i++) //遍历所有点,以防二分图不连通导致错误,见下例
{
if(col[i]!=-1) continue;
col[i]=1;
queue<int>q1;
q1.push(i);
while(!q1.empty()){
t=q1.front();q1.pop();
for(j=1;j<=n;j++)
if(a[t][j]){
if(col[j]==col[t]) return false;
if(col[j]==-1) col[j]=1-col[t],q1.push(j);
}
}
}
return true;
}
bool Find(int x){
for(int i=1;i<=n;i++){
if(!f[i] && a[x][i]){
f[i]=1;
if(link[i]==-1 || Find(link[i])){
link[i]=x;
return true;
}
}
}
return false;
}
int main()
{
int m,ans,i,x,y;
while(~scanf("%d%d",&n,&m)){
memset(a,0,sizeof(a));
memset(link,-1,sizeof(link));
for(i=0;i<m;i++){
scanf("%d%d",&x,&y);
a[x][y]=a[y][x]=1;
}
if(!Color()){
printf("No\n");continue;
}
ans=0;
for(i=1;i<=n;i++){
memset(f,0,sizeof(f));
if(Find(i)) ans++;
}
printf("%d\n",ans/2);
}
return 0;
}
/*4 3
2 3
2 4
3 4*/