TZOJ 5784: 团伙 并查集

描述

 

在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足:

1、我朋友的朋友是我的朋友;

2、我敌人的敌人是我的朋友;

所有是朋友的人组成一个团伙。告诉你关于这n个人的m条信息,即某两个人是朋友,或者某两个人是敌人,请你编写一个程序,计算出这个城市最多可能有多少个团伙?

 

 

输入

 

第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是敌人。

 

 

输出

 

一个整数,表示这n个人最多可能有几个团伙。

 

样例输入

 

6 4
1 1 4
0 3 5
0 4 6
1 1 2

样例输出

3

思路:对于朋友,直接并集,对于敌人,那么需要将所有敌人用二维数组存储起来,a[x][0]的数值代表x的敌人数量,然后让敌人并集

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1005;
 4 int a[N][N],f[N];
 5 int p,x,y;
 6 int find(int x)
 7 {
 8     if(f[x]!=x)f[x] = find(f[x]);
 9     return f[x];
10 }
11 void merger(int x,int y)
12 {
13     f[y] = x;
14 }
15 int main()
16 {
17     int n,m;
18     cin>>n>>m;
19     for(int i=1;i<=n;i++)f[i] = i;
20     for(int i=1;i<=m;i++)
21     {
22         cin>>p>>x>>y;
23         if(p==0)
24         {
25             if(find(x)!=find(y))
26                 merger(x,y);
27         }
28         else //a[x][0]代表x有a[x][0]个敌人,遍历敌人数量,然后将敌人和y并集 
29         {
30             for(int j=1;j<=a[x][0];j++) //y和x的敌人并集 
31             {
32                 int fa = find(y);
33                 int fb = find(a[x][j]);
34                 if(fa!=fb)merger(fa,fb);
35             }
36             for(int j=1;j<=a[y][0];j++) //x和y的敌人并集 
37             {
38                 int fa = find(x);
39                 int fb = find(a[y][j]);
40                 if(fa!=fb)merger(fa,fb);
41             }
42             a[x][++a[x][0]] = y; //将y加入x的敌人 
43             a[y][++a[y][0]] = x; //将x加入y的敌人 
44             
45         }
46     }
47     int ans = 0;
48     for(int i=1;i<=n;i++)
49         if(f[i]==i)ans++;
50     cout<<ans;
51      return 0;
52 }

 

posted @ 2023-03-15 13:35  CRt0729  阅读(28)  评论(0编辑  收藏  举报