P1892 [BOI2003]团伙

在这里插入图片描述

淳朴的并查集,思路也很简单~

思路:如果是两个人是好盆友,很自然就要将他们所在集合合并了,如果不是朋友比如x—y 是敌人

1.那么就将x与y的其他敌人合并,why?因为敌人的敌人就是朋友了(他们有共同的敌人~)

2.除此之外还要将y与x的其他敌人合并,why?下面就来解释这个问题~

比如上面的样例~假如我们不执行上面的第二点

E 1 4 将4与所有1的其他敌人合并,很显然没有。

F 3 5 合并 3 5

F 4 6 合并4 6

E 1 2 将2与所有1的其他敌人合并,也就是将4的祖先和2的祖先合并

在这里插入图片描述

合并好以后三个犯罪团伙,符合题意~

6
4
E 1 4
F 3 5
F 4 6
E 2 1

我们把样例的最后一个1 2 改成2 1,还是按照上第一个来操作的话
将1与2的其他敌人合并

很显然,这里不能合并~

在这里插入图片描述

最终会有4个团伙,所以我们还要将2与1的其他敌人合并~

下面是AC代码~

#include <iostream>
#include <vector>
#include <set>
#define Max 1005
using namespace std;
int par[Max];
vector<int > a[Max]; //a[x] 表示x和a[x]里面是敌人关系
int find_par(int x1); //寻找祖先节点
void unions(int x1,int x2); //将x1 x2的祖先合并 天下一家亲~
set<int> ss;
    int main()
    {
        int  N,M,p,q;
        char x;
        cin>>N>>M;
        for(int i=1;i<=N;i++)
        {
            par[i]=i;
        }
        for(int i=1;i<=M;i++)
        {
            cin>>x;
            cin>>p>>q;
            if(x=='F')
            {
                unions(p,q);
            }
            else
            {


                for(int j=0;j<a[p].size();j++)
                {
                    unions(a[p][j],q);
                }
                for(int j=0;j<a[q].size();j++)
                {
                    unions(p,a[q][j]);
                }
                a[p].push_back(q);
                a[q].push_back(p);
            }
        }
        for(int i=1;i<=N;i++)
        {
            ss.insert(find_par(i));
        }
        cout<<ss.size()<<endl;
        return 0;
    }

    int find_par(int x1) //寻找祖先节点
    {
        return x1==par[x1] ? x1 :par[x1]=find_par(par[x1]);//路径压缩
    }

    void unions(int x1,int x2) //将x1 x2的祖先合并 天下一家亲~
    {
        par[find_par(x1)]=find_par(x2);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值