《五月集训》第26天 并查集

Crazy_DM Crazy_DM 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

990. 等式方程的可满足性

解题思路:

1. 建立一个容器,初始值为容器下标的自身

2. 遍历容器,把==号的元素放入并查集,每个元素的值为他能够推出的结果。

3. 我们需要通过递归来推出这一个结果,若一个元素的元素不是他自身,那么他已经在一个等式系统了。假设a==d,此时a和d连通,也相当于以a(在数组中映射为0)为下标的元素和d连通,那么我们只需要修改a为下标的元素到d的连通性就好了,如果a下标所指代的元素,其作为下标在数组中对应的值还不是他自己,那么继续递归。

class UnionFind {
public:
    vector<int> hash;
    UnionFind() {
        hash.resize(26);
        iota(hash.begin(), hash.end(), 0);
    }
    
    int find(int id) {
        if(hash[id] == id) return id;
        hash[id] = find(hash[id]);
        return hash[id];
    }
    //在同一个等式系统中
    void unite(int id1, int id2) {
        hash[find(id1)] = find(id2);
    }
};

class Solution {
public:
    bool equationsPossible(vector<string>& equations) {
        UnionFind uf;
        for(auto it: equations) {
            if(it[1] == '=') {
                int id1 = it[0] - 'a';
                int id2 = it[3] - 'a';
                uf.unite(id1, id2);
            }
        }
        for(auto it: equations) {
            if(it[1] == '!') {
                int id1 = it[0] - 'a';
                int id2 = it[3] - 'a';
                if(uf.find(id1) == uf.find(id2)) return false;
            }
        }
        return true;
    }
};

1319. 连通网络的操作次数

解题思路:

跟上一题差不多的思路。

1.将元素放入并查集,如果两个元素已经在并查集的话,那么边的数++

2.遍历得到连通块的个数

3.如果连通块的个数 - 1不大于多余边的数量的话,那么就是可以连接的。

class UnionFind {
public:
    vector<int> hash;
    UnionFind(int n) {
        hash.resize(n);
        iota(hash.begin(), hash.end(), 0);
    }
    int find(int index) {
        if(index == hash[index]) return index; //该电脑目前还没有联通
        hash[index] = find(hash[index]);
        return hash[index];
    }
    bool unite(int index1, int index2) {
        int id1 = find(index1);
        int id2 = find(index2);
        if(id1 == id2) return false;
        hash[id1] = id2;
        return true;
    }
};

class Solution {
public: 
    int makeConnected(int n, vector<vector<int>>& connections) {
        UnionFind uf(n);
        int edge = 0; 
        int count = 0;
        //构建并查集
        for(auto it: connections) {           
            if(!uf.unite(it[0], it[1])) ++edge;
        }

        int arr[100010];
        memset(arr, 0, sizeof(arr));
        for(int i = 0; i < n; ++i) {
            int setID = uf.find(i);
            if(!arr[setID]) {
                arr[setID] = 1;
                ++count;
            } 
        }
        cout << edge << " " << count;
        if(edge >= count - 1) return count - 1;
        else return -1;
    }
};

 

...全文

相关推荐

评论
收藏 已收藏
分享
返回顶部
Crazy_DM
万人千题 64,203 成员 15,010 内容