团伙(group)
Description
在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足:
1、我朋友的朋友是我的朋友;
2、我敌人的敌人是我的朋友;
所有是朋友的人组成一个团伙。告诉你关于这n个人的m条信息,即某两个人是朋友, 或者某两个人是敌人,请你编写一个程序,计算出这个城市最多可能有多少个团伙?
Input
第1行为n和m,1<n<1000,1<=m<=100 000;
以下m行,每行为p x y,p的值为0或1,p为0时,表示x和y是朋友,p为1时, 表示x和y是敌人。
Output
一个整数,表示这n个人最多可能有几个团伙。
Sample Input 1
6 4
1 1 4
0 3 5
0 4 6
1 1 2
Sample Output 1
3
注意题目里的两句话:朋友的朋友是朋友,敌人的敌人是朋友,当p为1时表示x,y是敌人,那么很显然,x的敌人和y就是朋友,y的敌人和x也是朋友,这里用一个数组a来记录x,y的敌人,然后使用并查集的思想找他们的祖先,具体的看下面的代码
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int pp[maxn],a[maxn]; //pp数组用来存储父节点,a数组用来存储x,y的敌人
int m,n;
int p,x,y;
int find(int x) //查找函数+路径压缩
{
return x == pp[x] ? x : pp[x] = find(pp[x]);
}
int main()
{
cin >> n >> m;
for(int i = 1 ; i <= n*2 ; i++)
pp[i] = i;
for(int i = 0 ; i < m ; i++)
{
cin >> p >> x >> y;
int r1 = find(x); //找到r1的祖先
int r2 = find(y); //找到r2的祖先
if(!p) //如果p为0,说明x,y是朋友,那么r1和r2自然也是朋友
{
pp[r2] = r1; //所以让r2的父节点为r1
}
else
{
if(!a[x]) //如果a[x]为0,就说明x没有敌人,那y就是x的敌人
a[x] = y;
else //如果a[x]不为零,说明x的敌人为a[x],那么找到a[x]的父节点,其父节点是y的朋友,所以让r3的父节点为r2
{
int r3 = find(a[x]);
pp[r3] = r2;
}
if(!a[y]) //这里和上面一样,不多赘述
a[y] = x;
else
{
int r3 = find(a[y]);
pp[r3] = r1;
}
}
}
int cnt = 0;
for(int i = 1 ; i <= n ; i++)//最后只要判断一下结点指向自身的有多少个即可
{
if(pp[i] == i)
cnt++;
}
cout << cnt << endl;
return 0;
}