The Accomodation of Students
题目链接
题目大意
告诉你有一些人相互认识,现在让你分出两个组,每组中的人不能互相认识,求最多能分多少组人,需要注意的是A认识B,B认识C,但是这并不意味着A认识C。
题解
就是让你求一个二分图的最大匹配,求之前判断一下这个图是不是二分图就行了。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,m,g[205][205],a,b,flag[205],l[205],r[205],h1,h2,link[205];
bool vis[205];
bool bfs(int s)
{
if (flag[s]) return 1;
int q[205],h=0,t=0;
memset(q,0,sizeof(q));
q[h++]=s;
l[h1++]=s;
flag[s]=1;
while (h!=t)
{
int v=q[t++];
for (int i=1;i<=n;i++) if (g[v][i])
if (flag[i])
{
if (flag[i]==flag[v]) return 0;
}
else
{
flag[i]=flag[v]*-1;
q[h++]=i;
if (flag[i]==1) l[h1++]=i;
else r[h2++]=i;
}
}
return 1;
}
bool dfs(int u)
{
for (int i=0;i<h2;i++)
{
int v=r[i];
if (!vis[v] && g[u][v])
{
vis[v]=1;
if (!link[v] || dfs(link[v]))
{
link[v]=u;
return 1;
}
}
}
return 0;
}
int solve()
{
int ans=0;
memset(link,0,sizeof(link));
for (int i=0;i<h1;i++)
{
memset(vis,0,sizeof(vis));
if (dfs(l[i])) ans++;
}
return ans;
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
h1=0; h2=0;
memset(flag,0,sizeof(flag));
memset(g,0,sizeof(g));
for (int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
g[a][b]=1;
g[b][a]=1;
}
bool f=1;
for (int i=1;i<=n;i++) if (!bfs(i))
{
f=0;
printf("No\n");
break;
}
if (!f) continue ;
printf("%d\n",solve());
}
return 0;
}