首页 > 其他分享 >并查集

并查集

时间:2023-05-17 19:46:03浏览次数:34  
标签:int 查集 合并 fa 集合 find

并查集

并查集是一种用于处理集合合并和查询的数据结构,常用于连通性问题。它可以动态地添加和合并集合,并快速地查询两个元素是否在同一个集合中。 ————chatGPT

并查集被很多OIer认为是最简洁而优雅的数据结构之一,主要用于解决一些元素分组的问题。它管理一系列不相交的集合,并支持两种操作:

  • 合并(Union):把两个不相交的集合合并为一个集合。
  • 查询(Find):查询两个元素是否在同一个集合中。

并查集的时间复杂度主要取决于查找的复杂度,因为合并的复杂度一般较小。一般而言,使用路径压缩和按秩合并的优化方法,可以使单次操作的时间复杂度达到 O(log n)


基本代码

  • 数据
int fa[MAXN]; //代表节点的父节点
  • 初始化
inline void init(int n)
{
    for (int i = 1; i <= n; ++i)
        fa[i] = i; 
    // 初始状态所有节点的父节点都是它自己
}

关于inline函数, 看这里 (留个坑, 以后有空讲讲)

  • 查询
int find(int x)
{
    if(fa[x] == x)
        return x;
    else
        return find(fa[x]);
}
  • 合并
inline void merge(int i, int j)
{
    fa[find(i)] = find(j);
}

优化

并查集的优化主要包括路径压缩按秩合并两种方法。

  • 1. 路径压缩

在查找一个元素所在的集合时,可以将路径上的所有节点都直接连接到根节点上,这样可以使得后续的查找操作更快。路径压缩的实现方法:

int find(int x)
{
    return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
  • 2. 按秩合并

这种优化方法也叫加权标记法,在合并两个集合时,可以比较它们的深度(也叫秩),将深度较小的集合连接到深度较大的集合上,这样可以减少树的深度,提高操作效率。按秩合并的实现方法:

  • 初始化
inline void init(int n)
{
    for (int i = 1; i <= n; ++i)
    {
        fa[i] = i;
        rank[i] = 1;
    }
}
  • 合并
inline void merge(int i, int j)
{
    int x = find(i), y = find(j);    //先找到两个根节点
    if (rank[x] <= rank[y])
        fa[x] = y;
    else
        fa[y] = x;
    if (rank[x] == rank[y] && x != y)
        rank[y]++; 
        //如果深度相同且根节点不同,则新的根节点的深度+1
}
  • 综合使用路径压缩和按秩合并可以达到最优的时间复杂度,即单次操作的时间复杂度为 O(log n)

参考文献:

算法学习笔记(1) : 并查集 - 知乎 (zhihu.com)

算法与数据结构—— 并查集_酱懵静的博客-CSDN博客

通俗易懂地讲解《并查集》 - 知乎 (zhihu.com) python文献

标签:int,查集,合并,fa,集合,find
From: https://www.cnblogs.com/EraYes/p/17409910.html

相关文章

  • 【CF1012E】【LOJ2818】Cycle Sort(并查集)
    Description给定一个⻓为nn的数列,你可以多次进行如下操作:选定kk个不同的下标i1,i2…iki1,i2......
  • 并查集概述
      并查集基础一、概念及其介绍并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。并查集的思想是用一个数组表示了整片森林(parent),树的根节点唯一标识了一个集合,我们只要找到了某个元素的的树根,就能确定它在哪个集合里。二、适用说明并查集用在一些有......
  • [Week 19]每日一题(C++,数学,并查集,动态规划)
    目录[Daimayuan]T1倒数第n个字符串(C++,进制)输入格式输出格式样例输入样例输出解题思路[Daimayuan]T2排队(C++,并查集)输入格式输出格式样例输入1样例输出1样例输入2样例输出2样例输入3样例输出3数据规模解题思路[Daimayuan]T3素数之欢(C++,BFS)数据规模输入格式输出格式样例输入样......
  • 并查集的操作
    //并查集#include<stdio.h>#defineSIZE100intUFSets[SIZE];voidinitial(intS[])//初始化并查集全部设为-1即每一个元素都是独立的{for(inti=0;i<SIZE;i++){S[i]=-1;}}intFind(intS[],intx)//查找元素操作返回x所属根节点x指的是......
  • 带权并查集
    做了cf上一道题后发现我对并查集的理解不够深刻,顺带把带权并查集学一下。并查集初始化:对于一个集合A的所有元素,我们知道对于其中任意一个元素i,i€A。此时,我们可以认为i与A之间存在一条虚边,如果有新的元素要加入集合A,将该元素与A建一条边即可。这条边我们用数组fa[i]......
  • 6795 Connected Components 并查集
     描述 编写一个程序,读取SNS(社交网络服务)中的关系,并判断给定的用户对是否可以通过网络相互访问。 输入 第一行给出了两个整数n和m。n是SNS中的用户数,m是SNS中的关系数。SNS中的用户由ID0,1,...,n-1标识。在接下来的m行中,给出了关系。每个关系由两个整......
  • 2649: More is better 并查集
    王先生想要一些男孩帮助他完成一个项目。因为项目比较复杂,男生来的越多越好。当然有一定的要求。王先生选择了一个足够容纳孩子们的房间。没有被选中的男孩必须立即离开房间。一开始房间里有10000000个男孩,编号从1到10000000。经过王先生的选择,他们中仍然在这个房间里的任何两个......
  • 7922: 江湖 并查集
    描述 江湖上散落着各式各样的大侠,有上千个之多。他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的,就免不了要打一架。但大侠们有一个优点就是讲义气,绝对不打自己的朋友。而且他们信奉“朋友的朋友就是我的朋友”,只要是能通过朋友关系串联起来的,不管拐了多......
  • 并查集
    并查集将两个集合合并询问两个元素是否在一个集合当中基本原理:每个集合用一颗树来表示,树根的编号就是整个集合的编号.每个节点存储它的父节点,p[x]表示x的父节点.①如何判断树根if(p[x]==x)②如何求x的集合编号while(p[x]!=x)x=p[x]③如何合并......
  • 5760: 家庭问题 并查集
    描述 有n个人,编号为1,2,……n,另外还知道存在K个关系。一个关系的表达为二元组(α,β)形式,表示α,β为同一家庭的成员。当n,k和k个关系给出之后,求出其中共有多少个家庭、最大的家庭中有多少人?例如:n=6,k=3,三个关系为(1,2),(1,3),(4,5)此时,6个人组成三个家庭,即:{1,2,3}为一个家庭,{4,5}为一个家......