[BOI2003] 团伙
题目来源:https://www.luogu.com.cn/problem/P1892
题目描述
现在有 n n n 个人,他们之间有两种关系:朋友和敌人。我们知道:
- 一个人的朋友的朋友是朋友
- 一个人的敌人的敌人是朋友
现在要对这些人进行组团。两个人在一个团体内当且仅当这两个人是朋友。请求出这些人中最多可能有的团体数。
输入格式
第一行输入一个整数 n n n 代表人数。
第二行输入一个整数 m m m 表示接下来要列出 m m m 个关系。
接下来 m m m 行,每行一个字符 o p t opt opt 和两个整数 p , q p,q p,q,分别代表关系(朋友或敌人),有关系的两个人之中的第一个人和第二个人。其中 o p t opt opt 有两种可能:
- 如果
o
p
t
opt
opt 为
F
,则表明 p p p 和 q q q 是朋友。 - 如果
o
p
t
opt
opt 为
E
,则表明 p p p 和 q q q 是敌人。
输出格式
一行一个整数代表最多的团体数。
样例 #1
样例输入 #1
6
4
E 1 4
F 3 5
F 4 6
E 1 2
样例输出 #1
3
提示
对于 100 % 100\% 100% 的数据, 2 ≤ n ≤ 1000 2 \le n \le 1000 2≤n≤1000, 1 ≤ m ≤ 5000 1 \le m \le 5000 1≤m≤5000, 1 ≤ p , q ≤ n 1 \le p,q \le n 1≤p,q≤n。
设计思路
这道题很有意思,看起来像是并查集的题目,但根据敌人的敌人是朋友,朋友的朋友还是朋友我们可以看出,这道题类似扩展域的做法,具体做法见代码
代码
#include<iostream>
using namespace std;
const int N = 2010;
int p[N];
int n,m;
int find(int x){
if(x!=p[x])p[x]=find(p[x]);
return p[x];
}
int main(){
cin>>n>>m;
for(int i=1;i<=2*n;i++)p[i]=i;
while(m--){
char op;
int a,b;
cin>>op>>a>>b;
if(op=='F'){
//朋友
p[find(a)]=find(b);
}else{
p[find(a+n)]=find(b);
p[find(b+n)]=find(a);
}
}
int res=0;
for(int i=1;i<=n;i++){
if(p[i]==i){
res++;
}
}
cout<<res;
return 0;
}