团伙 并查集_[并查集]团伙rqnoj577

【题目描述】

1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。而且有一点是肯定的,就是:

我朋友的朋友是我的朋友。

我敌人的敌人也是我的朋友。

两个强盗是同一团伙的条件是当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你最多有多少个强盗团伙。

【输入格式】

输入的第一行是一个整数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是敌人。输入数据保证不会产生信息的矛盾。

【输出格式】

输出只有一行,表示最大可能的团伙数。

【输入样例】

6

4

E 1 4

F 3 5

F 4 6

E 1 2

【输出样例】

3

汪维正说这个题是并查集的经典例题。但是我一直没有仔细研究过并查集。只有在用kruscal时才会小小地用一下。今天我决定仔细弄一下并查集。

首先,如果两人是朋友,那么就把两人合并。

除此之外,我们再维护一个e[i],表示i的一个敌人。如果两人是敌人,那么如果e[i]为空,就更新e[i],否则,就把e[i]和j合并。根据敌人的敌人是朋友的原则,如果j和i是敌人,那么j同e[i]则是朋友,所以合并。同样的,对于i和e[j],也是如此。

最后统计一下根结点就行了。

Code:

#include

#include

#include

#include

using namespace std;

int n,m;

const int maxn=1000;

int f[maxn+10],e[maxn+10];

int find(int x)

{

if (f[x]==x)

return f[x];

f[x]=find(f[x]);

return

f[x];

}

void together(int a,int b)

{

int aa=find(a),bb=find(b);

f[aa]=f[bb];

}

int main()

{

freopen("577.in","r",stdin);

freopen("577.out","w",stdout);

scanf("%d%d",&n,&m);

for (int

i=1; i<=n; i++)

f[i]=i;

while

(m--)

{

char flag=(getchar(),getchar());

int a,b;

scanf("%d%d",&a,&b);

if (flag=='F') together(a,b);

else

{

if (!e[a]) e[a]=b;

else together(e[a],b);

if (!e[b]) e[b]=a;

else together(e[b],a);

}

}

int

ans=0;

for (int

i=1; i<=n; i++)

if (f[i]==i) ans++;

printf("%d\n",ans);

fclose(stdin);

fclose(stdout);

return 0;

}

成绩:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值