• 并查集——优秀的找爹模板题


    并查集的操作有三步,初始化,查找祖先与合并。

    既然并查集是来查找祖先的,那么初始化就必然是让每个点的祖先指向自己

    for(int i=1;i<=n;++i) fa[i]=i;

    查找操作就是不断地向上走,直到找到祖先为止

    while(x!=fa[x]) x=fa[x];

    合并操作就是把一个节点的祖先变为另一个节点的祖先。

    fa[find(a)]=find(b);//其中find(x)为x的祖先

    我们需对路径进行压缩。

    即当我们经过找到祖先节点后,回溯的时候顺便将它的子孙节点都直接指向祖先,使以后的查找复杂度变回O(logn)甚至更低 

    while(x!=fa[x]) x=fa[x]=fa[fa[x]];

    完整代码:

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<time.h>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef pair<int,int> pr;
    const double pi=acos(-1);
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define Rep(i,u) for(int i=head[u];i;i=Next[i])
    #define clr(a) memset(a,0,sizeof a)
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define sc second
    ld eps=1e-9;
    ll pp=1000000007;
    ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
    ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
    ll read(){
        ll ans=0;
        char last=' ',ch=getchar();
        while(ch<'0' || ch>'9')last=ch,ch=getchar();
        while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
        if(last=='-')ans=-ans;
        return ans;
    }//head
    
    int n,m,p,x,y,z;
    int fa[20005];
    
    
    int find_die(int x)//找爹函数 
    {
        while(fa[x]!=x) x=fa[x]=fa[fa[x]];
        //将它的子孙节点都直接指向祖先 
        return x;
    }
    
    void uni(int r,int k)//合并函数 
    {
        fa[k]=r;
    }
    
    inline void print(int x,int y)//输出函数 
    {
            if(find_die(x)==find_die(y)) cout<<"Y"<<endl;
            else cout<<"N"<<endl;
    } 
    
    int main()
    {
        n=read(),m=read();
        rep(i,1,n)
            fa[i]=i;
        rep(i,1,m)
        {
            z=read(),x=read(),y=read();
            if(z==1)
            {
            int r1=find_die(x);
            int r2=find_die(y);
            if(r1!=r2) uni(r1,r2);
            }
            else if(z==2)
                print(x,y);
        }
        
        return 0;
    }
  • 相关阅读:
    linux | 管道符、输出重定向
    php 升级php5.5 、php7
    mysql 启动失败
    centos7.2安装phpmyadmin
    php file_get_contents失败[function.file-get-contents]: failed to open stream: HTTP request failed!解决
    go println与printf区别
    前端 head 中mate 详解
    centos 7 安装mysql
    iOS数据持久化—数据库SQLite模糊查询
    C 语言字符串和格式化输入与输出
  • 原文地址:https://www.cnblogs.com/lcezych/p/10753182.html
Copyright © 2020-2023  润新知