题意:给出一些点以及一些边,问是否可分成二分图,如果可以输出大的集合的个数
思路:先判断是否是二分图,之后用匈牙利算法求最大匹配
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <cstring>
#define N 205
using namespace std;
int n,m,head[N],size,hd[N];
int vis[N];
struct node
{
int v,next;
}e[N*N];
void init()
{
memset(head,-1,sizeof(head));
memset(hd,-1,sizeof(hd));
size=0;
}
bool judge(int t)
{
for(int i=head[t];i!=-1;i=e[i].next)
{
if(!vis[e[i].v ])
{
vis[e[i].v ]=1;
if(hd[e[i].v ]==-1 || judge(hd[e[i].v ]))
{
hd[e[i].v ]=t;
return 1;
}
}
}
return 0;
}
int get_num()
{
int num=0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(judge(i)) num++;
}
return num;
}
void add(int u,int v)
{
e[size].v=v;
e[size].next=head[u];
head[u]=size;
size++;
}
bool dfs()
{
memset(vis,-1,sizeof(vis));
queue<int> q;
for(int i=1;i<=n;i++)
{
if(vis[i]==-1)
{
q.push(i);
vis[i]=0;
while(!q.empty())
{
int t=q.front();
q.pop();
for(int ii=head[t];ii!=-1;ii=e[ii].next)
{
if(vis[e[ii].v ]==-1)
{
if(vis[t]) vis[e[ii].v]=0;
else vis[e[ii].v]=1;
q.push(e[ii].v);
}
else if(vis[e[ii].v ]==vis[t]) return 0;
}
}
}
}
return 1;
}
int main()
{
int p,q;
while(scanf("%d %d",&n,&m)!=EOF)
{
init();
while(m--)
{
scanf("%d %d",&p,&q);
add(p,q);
add(q,p);
}
if(!dfs()) printf("No\n");
else
{
int num=get_num();
printf("%d\n",num/2);
}
}
return 0;
}