首页 > 其他分享 >并查集

并查集

时间:2024-08-24 09:04:03浏览次数:9  
标签:int 查集 合并 查询 fa find

并查集及其应用

咸鱼说并查集22年加入考研大纲,到目前(25考研之前)还没有考过,可以压一手。

定义

并查集用于解决元素分组的相关问题,也就是对于一组元素,挑出一个来当作代表。
并查集可以视作一种树状的数据结构,每个元素结点都有一个父节点(父节点可以是自己,此时这个结点为代表)。
并查集有 2 种操作:

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

并查集最重要的特性是,用集合中的一个元素结点代表整个集合

初始简易版本

初始化

一开始每个元素结点自己一个人一组,此时自己作为自己的父节点。
img

//初始化
int fa[N];
void init(int n)
{
    for (int i = 1; i <= n; ++i)
        fa[i] = i;
}

合并

合并需要找到两个集合的代表,把一个代表的父亲设为另一个代表,通常把前者的父亲设置为后置。
img

// 合并
void merge(int x, int y)
{
	int fx = find(x);
	int fy = find(y);
    if(fx == fy)return; // 同一个代表,同一个集合,不用合并
    fa[fx] = fy;
}

查询

用递归的方式,一步步网上找父亲,最后找到的为代表元素(即自己作为自己父亲的)。若两个元素在同一个集合,则它们查询到的代表是同一个。
img

// 查询
int find(int x)
{
    if(x == fa[x])
        return x;
    else{
        return find(fa[x]);
    }
}

简易版本的缺点

很明显,在合并的过程中,并查集可能退化成链表,影响进一步查询和合并的效率,为解决这个问题,有路径压缩按秩合并两种策略。

路径压缩版本

在查询过程中直接把父亲设置为最终查询到的代表元素(书上的根节点)。
老吕布了。

路径压缩的查询

img

// 查询
int find(int x)
{
    if(x == fa[x])
        return x;
    else{
        return fa[x] = find(fa[x]);  //父节点设为根节点,返回父节点
    }
    // 或者把上述代表写成一行
    return x == fa[x] ? x : (fa[x] = find(fa[x]));
}

初始化与合并跟简易版本一样。

按秩合并

这里要给结点赋予秩的属性,这里的秩可以是树的深度,也可以是结点个数,此处以树深为例。

按秩合并初始化

//初始化
int fa[N];
int rank[N];
void init(int n)
{
    for (int i = 1; i <= n; ++i)
    {
        fa[i] = i;
        rank[i] = 1; // 一开始一个一组,深度为1
    }
}

按秩合并

img

void merge(int x, int y){
    int fx = find(x);
    int fy = find(y);
    if(rank[fx] <= rank[fy]){
        fa[fx] = fy;
    }else{
        fa[fy] = fx;
    }
    if(rank[fx] == rank[fy] && fx != fy) // 两棵深度一样的树合并之后的新树深度+1
}

参考文章

算法学习笔记(1) : 并查集 - 知乎 (zhihu.com)
并查集 - OI Wiki (oi-wiki.org)
并查集可视化

标签:int,查集,合并,查询,fa,find
From: https://www.cnblogs.com/CauchyPt/p/18377084

相关文章

  • 学习笔记---并查集
    并查集并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。比如说,我们可以用并查集来判断一个森林中有几棵树、某个节点是否属于某棵树等。(1)朴素并查集:intp[N];//存储每个点的祖宗节点//返回x的祖宗节点intfind(in......
  • 并查集
    在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内竞赛题中,其特点是看似并不复杂,但数据量极大,若用传统的线......
  • 并查集(保姆级讲解)
    文章目录什么是并查集查找合并例题代码什么是并查集并查集是一种树形的数据结构。支持两种操作**查找:**确定某个元素在那个集合**合并:**将两个集合的元素合并在一起查找1.朴素查找2.优化查找合并1.朴素合并2.优化合并因为朴素合并的时间复杂度已经......
  • 并查集扩展
    并查集扩展目录并查集扩展普通并查集例题:1.洛谷P1197星球大战2.洛谷P1955程序自动分析带权并查集例题:1.洛谷P2024食物链2.洛谷P1196银河英雄传说3.洛谷P5937ParityGame扩展域并查集例题:1.洛谷P1525关押罪犯普通并查集例题:1.洛谷P1197星球大战链接:[P1197JSOI20......
  • 并查集(路径压缩法+启发式合并法)
    我们从一道例题看起:洛谷P1551亲戚。问题很简单,给出一个亲戚关系图,规定\(x\)和\(y\)是亲戚,\(y\)和\(z\)是亲戚,那么\(x\)和\(z\)也是亲戚,那么\(x\)的亲戚都是\(y\)的亲戚,\(y\)的亲戚也都是\(x\)的亲戚,再给定\(P_i\)和\(P_j\),询问他们是否是亲戚,输出Yes或......
  • 并查集
    并查集(递归写法)#include<bits/stdc++.h>usingnamespacestd;constintX=10010;intf[X];intn,m; //初始化voidinit(){ for(inti=0;i<X;i++){ f[i]=i; }}//查找上级是谁intfind(intx){ if(x!=f[x]){ returnf[x]=find(f[x]);//路径......
  • 【知识】并查集的单点删除 &【题解】SP5150
    \(\mathfrak{1st.}\)前言-->题目传送门<--原先这道题的难度是紫,我觉得题目翻译看不懂,就去讨论版发了个贴,然后题管更新了题目翻译,并且把难度降到了蓝……\(\mathfrak{2nd.}\)思路赶时间或嫌啰嗦的可以直接跳到『思路归纳』。我们先从普通并查集开始思考对于删除单点\(x\),......
  • 关于并查集
    关于冰茶姬简述冰茶姬是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节点表示对应集合中的元素。顾名思义,冰茶姬支持两种操作:合并(Union):合并两个元素所属集合(合并对应的树)查询(Find):查询某个元素所属集合(查询对应的树的根节点),这可以用于......
  • P5836 [USACO19DEC] Milk Visits S(树上并查集)
    核心思路对于相同颜色且相邻的点合并。若不在同一集合,则0若在同一集合,同色1异色0AC代码#include<bits/stdc++.h>usingnamespacestd;intfa[1145141];charcol[1145141];intn,m;intfind(intx){ if(x==fa[x]) returnx; returnfa[x]=find(fa[x]);}v......
  • *算法训练(leetcode)第四十七天 | 并查集理论基础、107. 寻找存在的路径
    刷题记录*并查集理论基础107.寻找存在的路径*并查集理论基础讲解107.寻找存在的路径题目地址直接套模板。结点编号从1开始,因此定义father数组时需要n+1个空间,否则会越界。时间复杂度:O(......