团伙
luogu 1892
代码:
定义对手的对手是朋友,朋友的朋友是朋友,现在有n个人和m组关系,如果两个人是朋友那么他们属于同一个团伙,问有多少个团伙
原题:
题目描述
1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。而且有一点是肯定的,就是:
我朋友的朋友是我的朋友;
我敌人的敌人也是我的朋友。
两个强盗是同一团伙的条件是当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你最多有多少个强盗团伙。
输入输出格式
输入格式:
输入文件gangs.in的第一行是一个整数N(2<=N<=1000),表示强盗的个数(从1编号到N)。 第二行M(1<=M<=5000),表示关于强盗的信息条数。 以下M行,每行可能是F p q或是E p q(1<=p q<=N),F表示p和q是朋友,E表示p和q是敌人。输入数据保证不会产生信息的矛盾。
输出格式:
输出文件gangs.out只有一行,表示最大可能的团伙数。
输入输出样例
输入样例#1:
6
4
E 1 4
F 3 5
F 4 6
E 1 2
输出样例#1:
3
解题思路:
记下每个人的敌人,如果遇到敌人,就和敌人的敌人合并,如果遇到朋友就直接合并
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,p,q,x1,y1,pd,ans,a[1005][1005],dad[1005];
char x;
int find(int dep){return dad[dep]==dep?dep:dad[dep]=find(dad[dep]);}//并查集
int main()
{scanf("%d %d",&n,&m);for (int i=1;i<=n;++i)dad[i]=i;for (int i=1;i<=m;++i){cin>>x;while (x!='E'&&x!='F') cin>>x;//读入scanf("%d %d",&p,&q);if (x=='F'){x1=find(p);//合并y1=find(q);dad[min(x1,y1)]=max(x1,y1);}else{for (int j=1;j<=a[p][0];++j)//敌人的敌人{if (a[p][j]==q) continue;x1=find(a[p][j]);y1=find(q);dad[min(x1,y1)]=max(x1,y1);}for (int j=1;j<=a[q][0];++j)//反过来也要{if (a[q][j]==p) continue;x1=find(a[q][j]);y1=find(p);dad[min(x1,y1)]=max(x1,y1);}a[p][++a[p][0]]=q;//记下来a[q][++a[q][0]]=p;}}for (int i=1;i<=n;++i){pd=1;for (int j=i+1;j<=n;++j)if (find(i)==find(j))//看是否在同一个团伙{pd=0;break;}if (pd) ans++;}printf("%d",ans);
}