http://acm.hdu.edu.cn/showproblem.php?pid=2444
题意:有n个人,和m种关系,代表a和b认识。要求将n个人放入到两个集合中,每个集合中的人互不认识,A集合中的人找B集合的人住房间,两个人一间,且两个人必须认识,问你最多能住多少间房间。
思路:先确定A、B集合中各有哪些人,我们可以用个数组表示每个人在哪个集合中,若有重复,则输出No,反之再找最大匹配。
代码:#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define maxn 205
int n,m,u,v;
int num[maxn];
int G[maxn][maxn];
int lx[maxn],ly[maxn],vis[maxn];
int DFS(int a) //深搜
{
for(int i=1;i<=n;i++)
{
if(G[a][i]==1 && !vis[i])
{
vis[i]=1;
if(ly[i]==0 || DFS(ly[i]))
{
ly[i]=a;
lx[a]=i;
return true;
}
}
}
return false;
}
int match()
{
int ans=0;
for(int i=1;i<=n;i++)
{
if(lx[i]==0)
{
memset(vis,0,sizeof(vis));
if(DFS(i))
ans++;
}
}
return ans/2;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(G,0,sizeof(G));
memset(lx,0,sizeof(lx)); //由于关系是双向的,所以用要两个数组lx和ly
memset(ly,0,sizeof(ly));
memset(num,0,sizeof(num)); //代表这个人在哪个集合中
int temp=0;
while(m--)
{
u,v;
scanf("%d%d",&u,&v);
G[u][v]=G[v][u]=1;
if(num[u]==0 && num[v]==0)
num[u]=1,num[v]=2;
else if(num[u]==1 && num[v]==0)
num[v]=2;
else if(num[u]==2 && num[v]==0)
num[v]=1;
else if(num[u]==0 && num[v]==1)
num[u]=2;
else if(num[u]==0 && num[v]==2)
num[u]=1;
else if(num[u]==num[v] && num[v]!=0)
temp=1;
}
if(temp==1)
{
printf("No\n");
continue;
}
printf("%d\n",match());
}
return 0;
}