• 并查集


    并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。 (摘自百度)


    关于并查集和路径压缩:

    现在我们假定 f[i] 表示第 i 个人的老大是谁。

    现在我们有甲,乙,丙三个人(分别用 a, b, c 表示)

    假设甲和乙打架了,甲做了丙的小弟。则有 f[a]=b

    后来甲打赢了丙

    那么丙就是甲的小弟了。有 f[c]=a

    但是如果我们这样表示,丙不能直接知道甲,容易自己人打自己人

    所以,我们必须直接让丙的大哥变成最大的老大。

    定义函数 find

    int find(int k){
        if(f[k]==k)return k;
        return find(f[k]);
    }//find 函数可以直接找到最大的老大
    
    f[c]=find(a);
    //丙的老大是甲

    这时,因为我们要路过他所有的上级,我们也可以顺便使途中经过的人的大哥也变成老大。

    //路径压缩
    int find(int k){
        if(f[k]==k)return k;
        return f[k]=find(f[k]);
        /* 
            即:
            f[k]=find(f[k]);
            return f[k];
        */
    }
    
    f[c]=find(a);

    简直是太巧妙了!

    而判定两个人的老大是否相等,只需

    if(find(a)==find(b))

    就好了。

    一些设定:

    • 一个人不能有两个老大。
    • 当已经有老大的人臣服时,老大也将成为胜利的人的小弟。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
        return x*f;
    }
    
    int n,m;
    int fa[5020000];
    
    int find(int x)
    {
        if(x==fa[x]) return x;
        return fa[x]=find(fa[x]);
    }
    
    void ans(int x,int y)
    {
        if(find(x)==find(y)) printf("Y
    ");
        else printf("N
    ");
    }
    
    void hebing(int x,int y)
    {
        fa[find(x)]=find(y);
    }
    int main()
    {
        n=read();
        m=read();
        for(int i=1;i<=n;i++) fa[i]=i;
        
        for(int i=1;i<=m;i++)
        {
            int opt,x,y;
            opt=read();x=read();y=read();
            if(opt==1) 
            {
                hebing(x,y);
            }
            else 
            {
                ans(x,y);
            }
        }
        
        return 0;
    }

     感谢巨神@     huangzirui 

  • 相关阅读:
    搜狗输入法用户体验
    Day06
    Day05
    Spark-RDD操作(26个常用函数附实例)
    软件工程培训第五天(hive进阶)
    hive窗口函数
    hive操作(行转列,列转行)
    Hive中使用case then分情况求和
    hive分组排序(rank函数+partiton实现)
    软件工程培训第四天总结,hive的学习
  • 原文地址:https://www.cnblogs.com/yxr001002/p/14063128.html
Copyright © 2020-2023  润新知