zoukankan      html  css  js  c++  java
  • 【图论_并查集】

    一种特殊的数据结构——并查集

    并查集的思想主要用来找一些数据之间的关系

    或许你并不知道,你的某个朋友是你的亲戚,他可能是你曾祖父的外公的女婿的外甥女的表姐的孙子。所以为了解决你周围的人和你是不是有亲戚关系,我们就需要并查集的思想qwq。

    思想:合并集合的思想,可以理解为找共同的祖先,在数学上或许可以看成把同源的人合并到一个集合里:

    (找不到图感性理解吧)

    总之概括一下就是一个合并查找的过程。(通俗一点:“找祖宗”)

    下面来看一个eg:

    【洛谷p1551】亲戚

    算法就一个“并查集”(孤零零),是很典型的例题了。

    思路:

    初始状态,每个人的父亲都是他自己qwq

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

    开始输入两个人的亲戚关系:

    1.寻找他们的祖先并合并

    如果他们不是同一个祖先,因为他们有亲戚关系,故把他们合并成一个集合

    int find_father(int x){//寻找祖先,递归操作
    if(father[x]!=x) return find_father(father[x]);
    return x;
    }
    
    /*int find_father(int x){//进行优化,使每个人的“father”直接指向”老祖宗“,避免重复递归的时间
        if(father[x]!=x)father[x]=find_father(father[x]);
        return father[x];
    }*/
    
    void unionn(int x,int y){//合并两个集合(因为通过不断”找father“,一定可以判断他们是一个集合中的,这里规定谁是谁的father看习惯)
        father[y]=x;
    }
    
    
    
    
    
    for(int i=1;i<=m;i++){
            cin>>mi>>mj;//输入某两个人的亲戚关系
            int r1=find_father(mi);//找mi的祖先
            int r2=find_father(mj);//找mj的祖先
            if(r1!=r2)unionn(r1,r2);//如果他们祖先不同,那么就合并(避免重复合并
        }

    查:查找两个人是否有亲戚关系:

    for(int i=1;i<=p;i++){
            cin>>pi>>pj;
            if(find_father(pi)==find_father(pj))
                cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
        }

    我们把代码也并查集一下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int n,m,p,mi,mj,pi,pj;
    int father[5001];
    void unionn(int x,int y){
        father[y]=x;
    }
    int find_father(int x){
        if(father[x]!=x)father[x]=find_father(father[x]);
        return father[x];
    }
    int main(){
        scanf("%d%d%d",&n,&m,&p);
        for(int i=1;i<=n;i++)
          father[i]=i;
        for(int i=1;i<=m;i++){
            cin>>mi>>mj;
            int r1=find_father(mi);
            int r2=find_father(mj);
            if(r1!=r2)unionn(r1,r2);
        }
        for(int i=1;i<=p;i++){
            cin>>pi>>pj;
            if(find_father(pi)==find_father(pj))
                cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
        }
    }

    end-

  • 相关阅读:
    将HTTP请求对象转成curl命令行
    图片爬虫实践
    [CF1499E] Chaotic Merge
    [ICPC2020南京I] Interested in Skiing
    [ICPC2018西安J] Philosophical … Balance
    [ICPC2018西安L] Eventual … Journey
    [ICPC2018西安I] Misunderstood … Missing
    [ICPC2018西安D] Deja vu of … Go Players
    [ICPC2018西安F] Interstellar … Fantasy
    [ICPC2020南京L] Let's Play Curling
  • 原文地址:https://www.cnblogs.com/zhuier-xquan/p/10758286.html
Copyright © 2011-2022 走看看