Codeforces Round #133 (Div. 2) B. Forming Teams B. Forming Teams 并查集的扩张
http://codeforces.com/problemset/problem/216/B
题意:
有n个人,要求你将他们平均分成两组进行球赛。给出m个敌对关系,每个人最多有两个敌对的人,属于敌对关系的两个人不能分到同一小组里面。输出不能被分到两个小组最少人数。
思路:
和poj的食物链题目类似,这里利用并查集的长度记录关系,每出现一个敌对关系就将他们合并。距离为0表示可以属于同一组,1表示是敌对关系。当出现的两个敌对关系在之前已经确定为同类关系,必然将其剔除。记录剔除的个数,最后检查剔除这些人之后的人数是偶数。
View Code
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string> #define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b) #define ll long long #define inf 0x7f7f7f7f #define MOD 1073741824 #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 100007 #define M 1000007 #define N 107 using namespace std; //freopen("data.in","r",stdin); int f[N],dep[N]; int num ; int find(int x){ if (x != f[x]){ int tmp = f[x]; f[x] = find(f[x]); dep[x] = (dep[tmp] + dep[x])%2; } return f[x]; } void Union(int x,int y){ int tx = find(x); int ty = find(y); if (tx != ty){ f[ty] = tx; dep[ty] = (dep[y] + dep[x] + 1)%2; } else{ if (iabs(dep[x] - dep[y])%2 == 0) num++; } } int main(){ // freopen("data.in","r",stdin); int n,m; int i; int a,b; while (~scanf("%d%d",&n,&m)){ CL(dep,0); num = 0; for (i = 1; i <= n; ++i) f[i] = i; for (i = 1; i <= m; ++i){ scanf("%d%d",&a,&b); Union(a,b); } if ((n - num)&1) printf("%d\n",num + 1); else printf("%d\n",num); } return 0; }