题解:
经典的并查集问题,将每一个敌对元素之间有关联的可以联系成一个环。
1:判断是不是奇数环,若是奇数环,说明要去掉一个人,板凳席+1,若不是则刚好偶数环可以将其分到两队,板凳席不加人。
2:如果就是单纯是两两敌对,则这两个人自然就可以分到两个不同的队中,板凳席不用加人
3:如果没有任何敌对关系,也就是前两种处理好之后剩余的人,他们可以随意放置在不同的队伍中,没有什么关系,所以判断剩余人数的奇偶性,若是奇数则板凳席+1。
#include<iostream>
#include<algorithm>
using namespace std;
int fa[101],num[101];
int i,j,n,m,k,q;
int ans,x,y,px,py;
int find(int x)//并查集模板
{
if(x!=fa[x])
fa[x]=find(fa[x]);
return fa[x];//递归最后返回祖先
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF){
ans=0;
for(i=0;i<=n;i++){//初始定义
fa[i]=i;
num[i]=1;//环中个数
}
while(m--){
scanf("%d%d",&x,&y);//x,y有仇就放在一个环里
px=find(x);
py=find(y);
if(px!=py)//说明还没有闭环,继续处理该环
{
fa[px]=py;
num[py]+=num[px];//将y的子节点也就是他的环个数加到px树上去
}
else//同宗的话:说明闭环了,可以开始结算环中元素的总个数了(因为题目给出一个人只有两个敌人,一开始已经有个敌人了,最后又出现一个敌人,说明闭环)
{
k=num[px]&1;//如果num[px]为奇数则&1为1,是偶数则为0
ans+=k;
}
}
q=(n-ans)&1;//最后出场去掉的人数:剩下的人若为奇数则减一
ans+=q;//加上最后去掉的个数
printf("%d\n",ans);
}
return 0;
}