并查集原理分析(代码片段)

ych9527 ych9527     2022-12-07     660

关键词:

1.并查集是什么

  • 在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时**,每个元素自成一个单元素集合**,然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一个元素归属于那个集合的运算。适合于描述这类问题的抽象数据类型称为并查集

2.并查集性质

image-20210714212416244

  • 由上图可知,并查集有如下几点性质
    • 数组下标对应集合中元素的编号
    • 根下标对应的内容为负数
    • 子元素下标对应的内容为根的下标(子元素下标对应的内容非负数)

3.并查集可以解决的问题

  • 查找元素属于哪个集合
    • 查找对应元素的根
  • 查看两个元素是否属于同一个集合
    • 判断两个元素的根是否相等
  • 将两个集合归并成一个集合
    • 将两个元素的根进行合并
  • 集合的个数
    • 查找根的个数

4.并查集模板

#include "test.h"

class UnionFindSet

public:
	UnionFindSet(int size)//传入元素的个数
	
		_arr.resize(size, -1);
	

	int FindRoot(int x)//给定一个下标寻找它的根
	

		while (_arr[x] >= 0)//大于等于0,表示里面存储的是根的下标
		
			x = _arr[x];
		
		return x;
	

	bool Union(int x1, int x2)//将两个下标对应的根,进行合并
	
		//找到两个根的位置
		int root1 = FindRoot(x1);
		int root2 = FindRoot(x2);
		
		if (root1 == root2)
			return false;

		_arr[root1] += _arr[root2];
		_arr[root2] = root1;

		return true;
	

private:
	vector<int> _arr;
;

5.并查集的应用

省份数量

有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。返回矩阵中 省份 的数量。

题解:

  • 典型的并查集题目
  • 首先每个为1的城市,本身都是一颗树,但是他们记录的下标表示两个城市相连,即将这两颗树相连
  • 最后统计并查集中根的数量,返回即可 -> 根的数量就是省的数量
class Solution 
public:

class UnionFindSet

public:
	UnionFindSet(int size)
	
		_arr.resize(size, -1);
	

	int FindRoot(int x)//给定一个下标寻找它的根
	
		while (_arr[x] >= 0)//大于等于0,表示里面存储的是根的下标
		
			x = _arr[x];
		
		return x;
	

	bool Union(int x1, int x2)//将两个下标对应的根,进行合并
	
		//找到两个根的位置
		int root1 = FindRoot(x1);
		int root2 = FindRoot(x2);
		
		if (root1 == root2)
			return false;

		_arr[root1] += _arr[root2];
		_arr[root2] = root1;

		return true;
	

    int Size()
    
        int n=0;
        for(auto&e:_arr)
        
            if(e<0)//为根
            n++;
        
        return n;
    

private:
	vector<int> _arr;
;
    int findCircleNum(vector<vector<int>>& isConnected) 
        UnionFindSet uft(isConnected.size());

        for(int i=0;i<isConnected.size();i++)
        
            for(int j=0;j<isConnected.size();j++)
            
                if(isConnected[i][j]==1)
                
                    uft.Union(i,j);
                
            
        

        return uft.Size();
    
;

等式方程的可满足性

给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:“a==b” 或 “a!=b”。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。

题解:

  • 如果两个字符相等,则放入同一个集合之中 -> 即他们的根相同
  • 如果两个字符不相等,则去集合之中查找他们的根 -> 根相同则返回false
class Solution 
public:
    class UnionFindSet
    
    private:
        vector<int> arr;
    public:
        UnionFindSet(int n)
        
            arr.resize(n,-1);
        

        int FindRoot(int x)//寻找根
        
            while(arr[x]>=0)//表示不是根
            
                x=arr[x];
            
            return x;
        

        bool Union(int x,int y)
        
            int root1=FindRoot(x);
            int root2=FindRoot(y);
            if(root1==root2)
            return false;

            arr[root1]+=arr[root2];
            arr[root2]=root1;
            return true;
        
    ;
    bool equationsPossible(vector<string>& equations) 
        //将相等的都放入一个集合之中
        //然后判断不相等的在不在一个集合-> 根相不相同

        UnionFindSet ufs(26);

        for(auto&e:equations)
        
            if(e[1]=='=')
            ufs.Union(e[0]-'a',e[3]-'a');
        
        for(auto&e:equations)
        
            if(e[1]!='=')
            
                int root1=ufs.FindRoot(e[0]-'a');
                int root2=ufs.FindRoot(e[3]-'a');
                if(root1==root2)
                    return false;
            
        
      return true;
    
;

数据结构--并查集(代码片段)

并查集并查集原理并查集实现并查集原理在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合,然后按一定的规律将归于同一组元素的集合合并。在此过程中要... 查看详情

关于并查集的一切全在这里了(代码片段)

文章目录并查集初识「并查集」常用术语「并查集」基本思想「并查集」的两个实现方式QuickFind方式实现并查集QuickFind工作原理:代码实现与验证时间复杂度QuickUnion方式实现并查集QuickUnion的工作原理为什么QuickUnion比QuickFind... 查看详情

详解并查集(代码片段)

文章目录并查集原理并查集实现并查集应用并查集原理在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合,然后按一定的规律将归于同一组元素的集合合并。... 查看详情

数据结构--并查集的原理及实现(代码片段)

一,并查集的介绍 并查集(Union/Find)从名字可以看出,主要涉及两种基本操作:合并和查找。这说明,初始时并查集中的元素是不相交的,经过一系列的基本操作(Union),最终合并成一个大的集合。而在某次合并之后,有一种... 查看详情

树--12---并查集(代码片段)

文章目录并查集并查集是一种树型的数据结构并查集结构1.并查集的实现API设计UF(intN)构造方法实现union(intp,intq)合并方法实现代码:测试:案例1:计算机网诺连接2.UF_Tree算法优化eleAndGourp数组API设计find(intp)查询方法实现unio... 查看详情

程序自动分析(并查集+排序)(代码片段)

...k=1,x==y,否则x!=y,如果矛盾,输出NO,否则YES对于k=1,并查集简单操作一下,k=0,如果find(x)==find(y),打个标记,输出NO;有一个需要注意的地方是,对于询问我们要进行sort,使k=1的情况先执行,这样可以保证最后判断的答案正... 查看详情

并查集(代码片段)

本文参考了【算法】并查集(DisjointSet)和并查集详解并查集原理并查集是一种用于处理不相交集合之间合并问题的数据结构,例如求连通子图、判断是否存在环、求最小生成树等。以判断图中是否有环为例,下图是一个无向图... 查看详情

hiho14无间道之并查集图论--并查集(代码片段)

传送门:无间道之并查集分析并查集的分析可以看上面的传送门,写的挺好的了。其实在我看来并查集就是一种方便的维护集合的一种技巧,提出了代表元素这一概念。MyACCode#include<bits/stdc++.h>#definerep(i,a,b)for(inti=a;i<=b;i++)u... 查看详情

并查集模板(代码片段)

关于并查集的原理这里就不加阐述,参考博文:https://www.tuicool.com/articles/Zb2qYzj1inta[maxn];2intfa[maxn];3voidUFinit(intx)//并查集的初始化45for(inti=0;i<x;i++)fa[i]=-1;67intFind(intx)//查找并返回节点x所属集合的根节点89ints;//查找位置10for( 查看详情

237.程序自动分析并查集(代码片段)

https://www.acwing.com/problem/content/description/239/这里的话,需要注意的是我们的范围特别的大,如果直接开数组会MLE。所以这里我是直接用了哈希表来映射。然后我们保存状态,先处理全部的相等的条件,再处理所有的... 查看详情

数据结构高阶第十一篇——并查集(原理+实现+应用)(代码片段)

⭐️今天要和大家介绍一个新的数据结构——并查集。听名字好像是把集合合并再查找元素,其实总体来说也是这样的,下面我们来和大家好好聊一聊这个玩意~⭐️博客代码已上传至gitee:https://gitee.com/byte-binxin/data-s... 查看详情

数据结构与算法分析-9-并查集(不相交集)(代码片段)

并查集(Disjoint Sets),直译即不相交集。 等价关系离散数学中对等价关系的定义:满足自反性、对称性和传递性的关系。集合A,∀(a,b),a,b∈A,满足aRb,则称R为A上的关系,若R满足以上三种性质,则为等价关系。... 查看详情

并查集模板并查集模板luogu-3367(代码片段)

题目描述简单的并查集模板输入描述第一行包含两个整数N、M,表示共有N个元素和M个操作。接下来M行,每行包含三个整数Zi、Xi、Yi当Zi=1时,将Xi与Yi所在的集合合并当Zi=2时,输出Xi与Yi是否在同一集合内,是的话输出Y;否则话... 查看详情

acwing237程序自动分析[离散化+并查集](代码片段)

题目在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。考虑一个约束满足问题的简化版本:假设x1,x2,x3,…x1,x2,x3,…代表程序中出现的变量,给定nn个形如xi=xjxi=xj或xi≠xjxi≠xj的变量... 查看详情

并查集和模拟堆(代码片段)

并查集:1.将两个集合合并。2.询问两个元素是否在一个集合当中。基本原理:每个集合用一颗树来表示。树根的编号就是整个集合的编号。每个节点存储他的父亲节点,p[x]表示x的父亲节点。问题1:如何判断树根:if(p[x]==x);问... 查看详情

并查集模板(代码片段)

并查集1.合并两个集合2.查询两个数是否在一个集合基本原理:每个集合用一棵树来表示,树根的编号就是整个集合的编号,每个结点存储他的父节点,p[x]表示x的父节点1.是否是一个集合if(find(a)==find(b))2.合并两个集合 p[find(a)... 查看详情

poj1988cubestacking带权并查集(代码片段)

...由于要实现大量数的移动和归属关系,所以想到可能要用并查集,但是毫无疑问,普通的并查集不能够实现统计在x下的cube个数这一功能,所以我们通过带权并查集来实现,每一个 查看详情

洛谷p1955[noi2015]程序自动分析[并查集,离散化](代码片段)

  题目传送门  题目描述在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。 考虑一个约束满足问题的简化版本:假设x1,x2,x3...代表程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相... 查看详情