题目描述

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
--------------------------------------------------------
分析:维护这种有传递性的父子关系,当然用并查集啦!   求助问一个问题,为什么两人(a , b)是朋友时不用unite(a+n,b+n),但2024食物链却要unite(a,b) unite(a+n,b+n) unite(a+n*2,b+n*2),知道的能不能在下面评论一下,谢谢啦。
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=;
int pa[maxn],table[maxn],rank[maxn],n;//num是以i为根的团伙数
void init()
{
for(int i=;i<maxn;i++)
{
pa[i]=i;
}
}
int find(int x)
{
if(pa[x]==x) return x;
else return pa[x]=find(pa[x]);
}
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y) return;
if(rank[x]<rank[y])
pa[x]=y;
else
{
pa[y]=x;
if(rank[x]==rank[y]) rank[x]++;
}
return;
}
int main()
{
int m,maxnum=;
char s[];
scanf("%d%d",&n,&m);
init();
for(int i=;i<m;i++)
{
int a,b;
scanf("%s%d%d",s,&a,&b);
if(s[]=='F')
{
unite(a,b);
// unite(a+n,b+n);
}
else
{
unite(a,b+n);
unite(a+n,b);
}
}
for(int i=;i<=n;i++)
table[find(i)]=;//有多少团伙
for(int i=;i<=*n;i++)
if(table[i]==) maxnum++;
printf("%d",maxnum);
return ;
}
05-14 04:14