题意:现在有一些学生给你一下朋友关系(不遵守朋友的朋友也是朋友),先确认能不能把这些人分成两组(组内的人要相互不认识),不能分的话输出No(小写的‘o’ - -,写成了大写的WA一次),能分的话,在求出来一对朋友可以住一个房间,最多可以开多少双人房(- -)
分析:使用并查集分组,如果出现矛盾就是不能分,可以分的话再用一组的成员求出最大匹配就OK了,还是比较水的....
*******************************************************************
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXN = 205;
///rl记录与根节点的关系
int fa[MAXN], rl[MAXN];
int FindFather(int x)
{
int k = fa[x];
if(fa[x] != x)
{
fa[x] = FindFather(fa[x]);
rl[x] = (rl[x]+rl[k]) % 2;
}
return fa[x];
}
int x[MAXN], y[MAXN], nx, N;
bool G[MAXN][MAXN], used[MAXN];
void InIt()
{
nx = 0;
memset(G, 0, sizeof(G));
for(int i=0; i<MAXN; i++)
{
fa[i] = i;
x[i] = y[i] = 0;
rl[i] = 0;
}
}
bool FindOk(int u)
{
for(int i=1; i<=N; i++)
{
if(G[u][i] && used[i] == false)
{
used[i] = true;
if(!y[i] || FindOk(y[i]))
{
y[i] = u;
return true;
}
}
}
return false;
}
int main()
{
int M;
while(scanf("%d%d", &N, &M) != EOF)
{
int i, u, v, ok=0;
InIt();
while(M--)
{
scanf("%d%d", &u, &v);
G[u][v] = G[v][u] = true;
int ru = FindFather(u);
int rv = FindFather(v);
if(ru == rv && rl[u] == rl[v])
ok = 1;
else if(ru != rv)
{
fa[ru] = rv;
rl[ru] = (rl[u]+rl[v]+1)%2;
}
}
if(ok)
printf("No\n");
else
{
for(i=1; i<=N; i++)
{
u = FindFather(i);
if(rl[i] == 0)
x[nx++] = i;
}
int ans = 0;
for(i=0; i<nx; i++)
{
memset(used, false, sizeof(used));
if(FindOk(x[i]) == true)
ans++;
}
printf("%d\n", ans);
}
}
return 0;
}