题目描述
在某城市里住着 n 个人,任何两个认识的人不是朋友就是敌人,而且满足:
1、我朋友的朋友是我的朋友;
2、我敌人的敌人是我的朋友;
所有是朋友的人组成一个团伙。告诉你关于这 n 个人的 m 条信息,即某两个人是朋友,或者某两个人是敌人,请你编写一个程序,计算出这个城市最多可能有多少个团伙?
输入格式
第 1 行为 n 和 m ,其中 1
输出格式
一个整数,表示这 n 个人最多可能有几个团伙。
样例数据 1
输入
6 4
1 1 4
0 3 5
0 4 6
1 1 2
输出
3
备注
【样例说明】
{1},{2,4, 6},{3,5} 共 3 个团伙。
解题报告:
并查集实现,算法如下:
1、如果 x 和 y 是朋友,则把 x 和 y 合并为一个团伙。
2、如果 x 和 y 是敌人,则继续判断:
(1)如果 x 的敌人 z 存在,在把 z 和 y 合并为一个团伙。因为敌人的敌人是朋友。
(2)如果 y 的敌人 z 存在,在把 z 和 x 合并为一个团伙。因为敌人的敌人是朋友。
3、统计团伙数量即可(即fa[x]=x的个数)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=1005;
int n,m,ans,fa[N],en[N][N];
int getfa(int x)
{
return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
void merge(int x,int y)
{
int fx=getfa(x),fy=getfa(y);
if(fx!=fy)fa[fy]=fx;
}
int main()
{
//freopen("lx.in","r",stdin);
int op,x,y;
n=getint(),m=getint();
for(int i=1;i<=n;i++)fa[i]=i;
while(m--)
{
op=getint(),x=getint(),y=getint();
if(op==0)merge(x,y);
else
{
for(int z=1;z<=n;z++)
if(en[x][z])merge(y,z);
for(int z=1;z<=n;z++)
if(en[y][z])merge(x,z);
en[x][y]=en[y][x]=1;
}
}
for(int i=1;i<=n;i++)
if(fa[i]==i)ans++;
cout<<ans;
return 0;
}