P1892 [BOI2003]团伙
作者:互联网
题目描述
现在有 n 个人,他们之间有两种关系:朋友和敌人。我们知道:
- 一个人的朋友的朋友是朋友
- 一个人的敌人的敌人是朋友
现在要对这些人进行组团。两个人在一个团体内当且仅当这两个人是朋友。请求出这些人中最多可能有的团体数。
输入格式
第一行输入一个整数 n 代表人数。
第二行输入一个整数 m 表示接下来要列出 m 个关系。
接下来 m 行,每行一个字符 opt 和两个整数 p,q,分别代表关系(朋友或敌人),有关系的两个人之中的第一个人和第二个人。其中 opt 有两种可能:
- 如果 opt 为
F
,则表明 p 和 q 是朋友。 - 如果 opt 为
E
,则表明 p 和 q 是敌人。
输出格式
一行一个整数代表最多的团体数。
说明/提示
对于 100\% 的数据,2≤n≤1000,1≤m≤5000,1≤p,q≤n。
输入输出样例
输入 #16 4 E 1 4 F 3 5 F 4 6 E 1 2输出 #1
3
分析:
利用并查集,用一个二维数组enemy[][]表示两个人之间的关系(当数组值为true时表示两人关系为敌人)如果两个人关系为朋友,就将两人合并为一组,选其中一人为另一人的根节点便于计算最终组数。其中要判断敌人的敌人为朋友,记为一组。
代码
#include <iostream> using namespace std; int team[1050]; int root(int n) //找n的根节点 { if (team[n]!=n) team[n]=root(team[n]); return team[n]; } void hebing(int i,int j) //将i和j合并 { int r1,r2; r1=root(i); r2=root(j); if (r1!=r2) team[r2]=r1; } int main() { int n,m,p,q,counter=0; char opt; bool enemy[1050][1050]; cin>>n>>m; for (int i=1;i<=n;i++) team[i]=i; //初始化将每个人的根节点设为自己 for (int i=1;i<=m;i++) { cin>>opt>>p>>q; if (opt=='F') hebing(p,q); //为朋友,则合并 if (opt=='E') { enemy[p][q]=true; enemy[q][p]=true; //p和q互为敌人 for (int i=1;i<=n;i++) { if (enemy[p][i]) hebing(q,i); //p和q、p和i都是敌人,则q和i是朋友,合并 if (enemy[q][i]) hebing(p,i); } } } for (int i=1;i<=n;i++) { if (team[i]==i) counter++; } cout<<counter; return 0; }
标签:opt,enemy,int,P1892,朋友,team,BOI2003,敌人,团伙 来源: https://www.cnblogs.com/branthx/p/16412154.html