并查集(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;
    }
};
//......
相关文章
|
算法 测试技术
并查集详解 (转)
http://blog.csdn.net/dellaserss/article/details/7724401 我从CSDN转的文章,原文作者我也不懂是谁,文章写得真的是诙谐幽默,使得内容更容易理解了。
803 0
并查集路径压缩
如何描述一个复杂的连接关系?如图,很容易判断紧邻的2个人关系,但中间的连接很多很乱,怎么判断出两个人的关系呢?并查集就是一种结构,通过保存节点以及节点上的标签,来判断这两个节点是否连接在一起。
1493 0
|
算法
并查集-连通性问题
连通性问题 比如随意给你两个点,让你判断它们是否连通?或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块。 以下面这组数据输入数据来说明 4 2 1 3 4 3  第一行告诉你,一共有4个点,2条路。
848 0
畅通工程 杭电oj1863 并查集实现
畅通工程 杭电oj1863 并查集实现
83 0
|
存储 Python
【23. 并查集】
**用途**: - 将俩个集合合并 - 询问俩个元素是否在一个集合当中 **基本原理**: - 每个集合用一棵树来表示。树根的编号就是整个集合的编号,每个节点存储它的父节点,`p[x]`表示x的父节点。
163 0
【23. 并查集】
|
测试技术
畅通工程(并查集)
Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。
976 0

热门文章

最新文章