题意:给出n个人以及m组相互认识的人,将这n个人放到两个集合里面去,每个集合里的人都互不相识,如果无法做到,就输出No,如果可以,就输出两个集合的最大匹配数
解题思路:先判断这n个人能否构成二分图,判断方法很简单,一开始所有人都是0,将相互认识的人标记为1,-1,如果相互认识,且数值相同,则不能构成二分图,反之即可,接下来就是简单的二分匹配
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
int a[205],b[205];
int p[205],vis[205][205];
bool use[205];
int g[205];
int la,lb;
bool find(int x)
{
for(int i=1;i<lb;i++)
{
if(vis[x][b[i]] == 1 && use[b[i]] == false)
{
use[b[i]] = 1;
if(g[b[i]] == 0 || find(g[b[i]]))
{
g[b[i]] = x;
return true;
}
}
}
return false;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int x,y;
memset(p,0,sizeof(p));
memset(vis,0,sizeof(vis));
int flag=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
vis[x][y] = vis[y][x] = 1;
if(p[x]==0)
{
if(p[y]==0)
{
p[x] = 1;
p[y] = -1;
}
else p[x] = -p[y];
}
else
{
if(p[y]==0) p[y] = -p[x];
else
{
if(p[x]==p[y]) flag=1;
}
}
}
if(flag==1)
{
printf("No\n");
continue;
}
la=1,lb=1;
for(int i=1;i<=n;i++)
{
if(p[i]==1)
{
a[la] = i;
la++;
}
else if(p[i]==-1)
{
b[lb] = i;
lb++;
}
}
int all=0;
memset(g,0,sizeof(g));
for(int i=1;i<la;i++)
{
memset(use,0,sizeof(use));
if(find(a[i])) all+=1;
}
printf("%d\n",all);
}
return 0;
}