并查集,实现简单,功能强大

并查集中,只需要实现最简单的 getFather(Node)  以及  unionNode(Node, Node)  就能使用了。

在处理是否联通问题里面,特别好用,写一下基本实现过程, MARK 一下

主要有一个 faMap 来存储每个节点的父节点,可以为哈希表,也可以为 vector 

在节点为 int 型,并且元素范围固定的情况下,vector 更高效

sizeMap 同理,存储每个并查集的大小,

获取父亲节点  getFa 函数,通过递归调用来实现查找 父亲节点, 为的是,  在递归返回的过程中,

faMap[a] = fa;   这一句来使较深的节点全都指向头结点

两个节点合并的操作,会返回这两个节点合并后的  并查集的大小,通常用于 提前终止迭代过程,

即所有节点都在一个并查集中时,后面就再也不会发生 合并的操作了

    vector faMap;
    vector sizeMap;
    int getFa(int a){
        int fa = faMap[a];
        if(fa != a) fa = getFa(fa);
        // 把并查集变扁平
        faMap[a] = fa;
        return fa;
    }

    int unionMap(int a, int b){
        int fa = getFa(a), fb = getFa(b);
        if(fa == fb) return sizeMap[fa];
        if(sizeMap[fa] > sizeMap[fb]) 
            sizeMap[fa] += sizeMap[fb], faMap[fb] = fa;
        else sizeMap[fb] += sizeMap[fa], faMap[fa] = fb;
        return max(sizeMap[fa], sizeMap[fb]);
    }
    // 初始化并查集
    faMap.resize(N), sizeMap.resize(N);
    for(int i=0; i

通过一个例题来说明一下 1135. 最低成本联通所有城市

解题思路,先把链接按照权重排序,然后初始化并查集,

最后遍历权重数组,查看当前链接的两个点是否同属一个并查集,若属于就不进行 合并操作,

若不属于,则进行合并操作, res  需加上当前权重,因为 合并操作会返回当前并查集的大小

若返回大小为  N  , 则证明所有城市联通,提前终止返回  res  即可,若走到最后也没返回,则证明无法将所有城市联通

class Solution {
private:
    vector faMap;
    vector sizeMap;
    int getFa(int a){
        int fa = faMap[a];
        if(fa != a) fa = getFa(fa);
        faMap[a] = fa;
        return fa;
    }
    // 确认两个点为父节点,并且不相连
    int unionMap(int fa, int fb){
        // int fa = getFa(a), fb = getFa(b);
        // if(fa == fb) return sizeMap[fa];
        if(sizeMap[fa] > sizeMap[fb]) 
            sizeMap[fa] += sizeMap[fb], faMap[fb] = fa;
        else sizeMap[fb] += sizeMap[fa], faMap[fa] = fb;
        return max(sizeMap[fa], sizeMap[fb]);
    }
public:
    int minimumCost(int N, vector>& conections) {
        if(N == 1) return 0;
        if(N > conections.size() + 1) return -1;
        // 初始化并查集
        faMap.resize(N), sizeMap.resize(N);
        for(int i=0; i& a, vector& b){ return a[2] < b[2]; });
        for(int i=0; i

 

再通过一个例题来说明一下  547. 朋友圈

这个题目应用并查集就很简单了, 连 sizeMap  都不需要都可以做,判断是否有线,然后放到一起就行

class Solution {
private:
    vector faMap;
    int getFa(int a){
        int fa = faMap[a];
        if(fa != a) fa = getFa(fa);
        faMap[a] = fa;
        return fa;
    }
    void unionMap(int a, int b){
        int fa = getFa(a), fb = getFa(b);
        if(fa == fb) return ;
        faMap[fb] = fa;
    }
public:
    int findCircleNum(vector>& M) {
        int N = M.size(), res = 0;
        // 初始化并查集
        faMap.resize(N);
        for(int i=0; i

 

 

你可能感兴趣的:(日常学习)