并查集(UnionFind)总结

简介: 并查集(UnionFind)总结

一、并查集-基础版

例题:leetcode-990:等式方程的可满足性

class UnionFind{
private:
    vector<int> parent;
public:
    UnionFind(int n){
        parent.resize(n);
        iota(parent.begin(),parent.end(),0);
    }
    int find(int index){//查找根节点
        if(index==parent[index]) return index;
        parent[index]=find(parent[index]);//所有关联节点的父节点都指向关联的根节点
        return parent[index];
    }
    void unite(int index1,int index2){//关联(将第一个变量的根节点的父节点指向第二个变量的根节点)
        parent[find(index1)]=find(index2);
    }
};

二、并查集-操作二维数组

只要将二维转化为一维即可比如n*n的矩阵

对于一个坐标为(x,y)的点,对应索引为x*n+y

class UnionFind{
private:
    vector<int> parent;
public:
    UnionFind(int n){
        parent.resize(n);
        iota(parent.begin(),parent.end(),0);
    }
    int find(int index){//查找根节点
        if(index==parent[index]) return index;
        parent[index]=find(parent[index]);//所有关联节点的父节点都指向关联的根节点
        return parent[index];
    }
    void unite(int index1,int index2){//关联(将第一个变量的根节点的父节点指向第二个变量的根节点)
        parent[find(index1)]=find(index2);
    }
};
int main(){
  int m,n;
  cin>>m>>n;
  vector<vector<int>> mat(m,vector<int>(n));
  //...
  UnionFind uf(m*n);
}

三、并查集-获得集合数量

思路:不同的集合,每次合并,都会让集合数量-1

例题:leetcode-547:省份数量

class UnionFind{
private:
    vector<int> parent;
    int setNum;
public:
    UnionFind(int n){
        parent.resize(n);
        iota(parent.begin(),parent.end(),0);
        setNum=n;//初始集合数量为n
    }
    int find(int index){
        if(parent[index]==index) return index;
        parent[index]=find(parent[index]);
        return parent[index];
    }
    void unite(int index1,int index2){
        int p1=find(index1);
        int p2=find(index2);
        if(p1!=p2){//如果两个集合不是同一个,那么合并集合,集合数量减一
            parent[p1]=p2;
            setNum--;
        }
    }
    int getSetNum(){
        return setNum;
    }
};

四、并查集-获得每个集合中元素的数量

每个元素的数量通过size数组,初始化为1(刚开始每个元素都是一个集合)。

我们只把数量保存在父节点上,也就是说size[find(index)]去获取当前index对应的集合数量

只要将子节点的数量全部转移给父节点就行了,然后子节点的数量置空。

通过getSize去获取对应index的集合的元素数量

例题:leetcode-827:最大人工岛

class UnionFind{
public:
    vector<int> parent;
    vector<int> size;
    UnionFind(int n){
        parent.resize(n*n);
        size.resize(n*n,1);
        iota(parent.begin(),parent.end(),0);
    }
    int find(int index){
        if(index==parent[index]) return index;
        return parent[index]=find(parent[index]);
    }
    void unite(int index1,int index2){
        int p1=find(index1),p2=find(index2);
        parent[p1]=p2;
        if(p1!=p2){//如果相等,会出现把size[p1]=size[p2]=0 都清空的异常情况
            size[p2]+=size[p1];
            size[p1]=0;
        }
    }
    int getSize(int index){
        return size[find(index)];
    }
};

五、并查集+带权有向图

根本不同的应用场景,权重变化有着不同的传递方式。

下面以leetcode-399:除法求值为例

class UnionFind{
private:
    vector<int> parent;
    vector<double> weight;
public:
    UnionFind(int n){
        parent.resize(n);
        weight.resize(n);
        for(int i=0;i<n;i++){
            parent[i]=i;
            weight[i]=1;
        }
    }
    int find(int index){
        if(index==parent[index]) return index;
        int origin=parent[index];
        parent[index]=find(parent[index]);//同时会把父节点的weight也更新好
        weight[index]*=weight[origin];
        return parent[index];
    }
    void unite(int  index1,int index2,double value){
        int p1=find(index1);
        int p2=find(index2);
        if(p1!=p2){
            parent[p1]=p2;
            weight[p1]=weight[index2]*value/weight[index1];
        }
    }
    double isConnected(int index1,int index2){
        int p1=find(index1);
        int p2=find(index2);
        if(p1==p2){
            return weight[index1]/weight[index2];
        }
        else return -1;
    }
};
//......
相关文章
|
JSON JavaScript API
Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)
Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)
|
数据安全/隐私保护
计算机四级网络工程师等级考试题库软件---百度云分享
做件好事,考四级的兄弟们一起共勉~~~ 链接:https://pan.baidu.com/s/1im4BDVZofZbT9f5PZtsxdA 密码:9i5h ​ ​支持一下呗
2794 0
|
小程序 开发工具 git
【微信小程序】-- uni-app 项目--- 购物车 -- 配置 tabBar 效果(五十一)
【微信小程序】-- uni-app 项目--- 购物车 -- 配置 tabBar 效果(五十一)
|
JavaScript 前端开发 安全
JavaScript函数详解
JavaScript函数的详细解析,包括函数的定义和调用方式(如一般格式、匿名函数、构造函数、自调用函数、箭头函数和严格模式)、函数参数(arguments对象、可变参数、默认参数值)、闭包的概念和应用实例。
JavaScript函数详解
|
测试技术 UED
软件测试中的探索性测试:一种创新的质量保证方法
在软件开发的生命周期中,测试阶段扮演着至关重要的角色。传统的软件测试方法,如自动化测试和回归测试,虽然在一定程度上保证了软件质量,但它们往往依赖于预定义的测试用例和脚本,可能无法覆盖所有用户场景和边缘情况。为了克服这些限制,探索性测试作为一种创新的质量保证方法应运而生。本文将深入探讨探索性测试的概念、优势以及如何有效地实施它,以帮助读者更好地理解和应用这种测试技术。
|
存储 PyTorch API
Pytorch入门—Tensors张量的学习
Pytorch入门—Tensors张量的学习
196 0
|
存储 缓存 监控
内存优化 | Bitmap优化
在内存优化中,优化 Bitmap 占用的内存效果最为明显,在 Android 里面,大部分 OOM,都是 bitmap 占用资源过大导致的,那么问题来了 如何防止 bitmap 占用资源过大导致 OOM?Android 系统何时会发生 OOM?怎样搭建线上线下一体化内存监控体系?Drump 文件过大,我们线上如何查看?线下监控那些工具你会用吗?关于 Native 层的内存泄漏该如何解决?图片监控你做过哪些努力?内存抖动为什么会引起 OOM?内存监控里面采集方式有哪些? 看完本文,希望可以以本文为索引,然后依次排雷解决上述问题,这样你也是这个领域的专家了
710 0
内存优化 | Bitmap优化
|
机器学习/深度学习 数据可视化 TensorFlow
【2023年最新】提高分类模型指标的六大方案详解
【2023年最新】提高分类模型指标的六大方案详解
483 0
|
存储 算法 安全
【数据结构】C#实现常用数据结构总结
自行整理的C#常见数据结构笔记。
676 0
【数据结构】C#实现常用数据结构总结