题意:给你N个学生与M对关系,每个关系形如(i,j),表示第i个学生与第j个学生相互认识. 现在要你将N个学生分成两组,每组中的任意两个学生都不相互认识.如果N个学生能分组的话,那么就将这N个学生放到尽量多的双人房中去.每个房间放2个相互认识的人.问你最多需要多少房间?
思路:先判断是否二分图,然后和POJ1466同样的做法
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int maxn=1000;
struct Max_Match
{
int n,m;
vector<int> g[maxn];
bool vis[maxn];
int left[maxn];
int color[maxn];
void init(int n)
{
this->n=n;
// this->m=m;
for(int i=1;i<=n;i++) g[i].clear();
memset(left,-1,sizeof(left));
}
bool bipartite(int u)
{
for (int i = 0;i<g[u].size();i++)
{
int v = g[u][i];
if (color[v] == color[u])
return false;
else if (color[v]==0)
{
color[v]=3-color[u];
if (!bipartite(v))
return false;
}
}
return true;
}
bool match(int u)
{
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(!vis[v])
{
vis[v]=true;
if(left[v]==-1 || match(left[v]))
{
left[v]=u;
return true;
}
}
}
return false;
}
int solve()
{
memset(color,0,sizeof(color));
for (int i = 1;i<=n;i++)
if(!color[i])
{
color[i]=1;
if (!bipartite(i))
return -1;
}
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(match(i)) ans++;
}
return ans;
}
}MM;
int T;
int main()
{
int n,m;
while (scanf("%d%d",&n,&m)!=EOF)
{
MM.init(n);
for (int i = 1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
MM.g[u].push_back(v);
MM.g[v].push_back(u);
}
int ans = MM.solve();
if (ans == -1)
printf("No\n");
else
printf("%d\n",ans/2);
}
}