zoukankan      html  css  js  c++  java
  • P3367 【模板】并查集

    定义

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

    并查集

    1.初始化
    把每个点所在集合初始化为其自身。
    通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为O(N)。
    void init(){
        for(int i=1;i<=n;i++) fa[i]=i;
    }
    2.查找
    查找元素所在的集合,即根节点。(注意,fa数组表示的不一定是父亲,大部分是祖宗,要用递归的路径压缩实现)
    int find(int x){
        if(fa[x]==x) return x;
        return find(fa[x]);
    }
    3.合并
    将两个元素所在的集合合并为一个集合。
    通常来说,合并之前,应先判断两个元素是否属于同一集合,这可用上面的“查找”操作实现。
    void merge(int x,int y){
        x=find(x),y=find(y);
        if(x<y) fa[y]=x;
        else fa[x]=y;
    }

    4.最后的最后

    好了,不说了,直接上题目

    题目

    题目描述

    如题,现在有一个并查集,你需要完成合并和查询操作。

    输入输出格式

    输入格式:

    第一行包含两个整数N、M,表示共有N个元素和M个操作。

    接下来M行,每行包含三个整数Zi、Xi、Yi

    当Zi=1时,将Xi与Yi所在的集合合并

    当Zi=2时,输出Xi与Yi是否在同一集合内,是的话输出Y;否则话输出N

    输出格式:

    如上,对于每一个Zi=2的操作,都有一行输出,每行包含一个大写字母,为Y或者N

    输入输出样例

    输入样例#1: 复制
    4 7
    2 1 2
    1 1 2
    2 1 2
    1 3 4
    2 1 4
    1 2 3
    2 1 4
    输出样例#1: 复制
    N
    Y
    N
    Y
    

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据,N<=10,M<=20;

    对于70%的数据,N<=100,M<=1000;

    对于100%的数据,N<=10000,M<=200000。

    分析

    2019年夏天,NBA自由市场开始了,无数巨星离开了自己的队伍去其他队争冠去

    这道题是一道普通的并查集,代码比较短,不是特别难,首先是要合并,然后再去判断是否在一个集合,总之来说可以看做NBA的球员在不在一个队

    代码

    #include<iostream>
    using namespace std;
    const int N=10100;
    int fa[N],n,m;
    void init(){
        for(int i=1;i<=n;i++) fa[i]=i;//每个球员都是老大
    }
    int find(int x){//寻找老大看是否是一队 
        if(fa[x]==x){
            return x;
        }
        return find(fa[x]);
    }
    void unite(int x,int y){//合并两名球员在一队 (例:合并伦纳德和乔治一队,选老大) 
        x=find(x),y=find(y);
        if(x<y) fa[y]=x;
        else fa[x]=y;
    }
    int main(){
        scanf("%d%d",&n,&m);
        init();//初始化 
        for(int i=1;i<=m;i++){
            int u,v,z;
            scanf("%d%d%d",&z,&u,&v);
            if(z==1) unite(u,v);//合并两名球员 
            if(z==2){
                if(find(u)==find(v)) printf("Y
    ");//如果在是一队的 (如果他们的老大相同,例:浓眉哥和考神的老大是詹姆斯DXX) 
                else printf("N
    ");//如果不是(例:哈登老大是威少【以前的】,而西帝老大是大帝) 
            }
        }
        return 0;
    }
  • 相关阅读:
    Java 的 多态和构造方法
    java 的 抽象类、接口
    java 的 封装 、继承
    eclipse的安装和基本使用、面向对象、类和对象
    方法的重载、引用数据类型、 ArrayList集合
    SQL单行函数
    JAVA
    mysql约束
    MYSQL的常用属性
    mysql的索引
  • 原文地址:https://www.cnblogs.com/earth833/p/11206852.html
Copyright © 2011-2022 走看看