并查集

并查集

    让我们先来了解一下什么是并查集 假设现在有10个人 给你一些信息判断他们有多少个班

    1和2是一个班

    3和4是一个班

    5和2是一个班

    4和6是一个班

    2和6是一个班

    8和7是一个班

    9和7是一个班

    1和6是一个班

    2和4是一个班

    解决这个问题 先假设他们都不在一个班 每个人都有独立的班级 然后利用条件进行合并 最终可以得到 5 2 1 3 4 6是一个班级的

7 8 9是一个班级的 10是一个班级的

    那具体应该怎样去实现呢 去找每个人的BOSS 然后让这个BOSS归顺另一个BOSS 我们假设右边的BOSS都归顺于左边的BOSS 

    我们用一个数组f来储存开始的状态 即每个人都有自己独立的班级 换句话说就是每个人都是自己的BOSS 此时f[i]=i

    我们知道1和2是同一班级的之后 让2去归顺于1 即f[2]=1 这时2和1都是同一个班级1的了 

    接下来是3和4 他们的boss也都是自己 同上得f[4]=3

    5和2 2的boss是1 5的boss是5 这时就为f[1]=5 

    4和6 4的boss是3 6的boss是他自己 这时 f[6]=3

    同上进行修改 在修改的过程中还有一个小技巧让找boss的时间减少 就是在找boss的过程中把中间的学生值都修改为boss 这样会加快找boss的速度  具体解释让我们来看代码

    

# include <iostream>
# include <cstdio>
using namespace std;
int f[1100]={0},n,m,k,sum=0;
void init()//让每个人都是自己的boss 都有自己独立的班级
{
    int i;
    for(i=1;i<=n;i++)
        f[i]=i;
    return ;
}
int getboss(int v)//这里就是找这个人的boss 利用递归一直到找到boss为止
{
    if(f[v]==v)//如果这个人的班级就是自己的班级 那么他就是boss 因为他并没有归顺于别人
        return v;
    else
    {
        f[v]=getboss(f[v]);//这里就是在路径中进行压缩 在找boss的过程中把路径中的人的值都改为找到的boss的编号
        //这样可以加快找boss的速度
        return f[v];
    }
}
void merge(int v,int u)//对找到的boss进行归顺合并
{
    int t1,t2;
    t1=getboss(v);
    t2=getboss(u);//分别找到左右的boss
    if(t1!=t2)//判断两个boss是不是一个
    {
        //如果不是一个 那就让右边归顺于左边
        f[t2]=t1;
    }
    return ;
    
}
int main()
{
    int i,x,y;
    scanf("%d%d",&n,&m);
    init();//进行初始化
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        merge(x,y);
    }
    for(i=1;i<=n;i++)
    {
        if(f[i]==i)//这个人没有归顺于任何人 则这就是一个班级
            sum++;
    }
    printf("%d\n",sum);
    return 0;
}
/*
 10 9
 1 2
 3 4
 5 2
 4 6
 2 6
 8 7
 9 7
 1 6
 2 4
 
 3
 */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值