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

Crazy_DM 2022-05-26 22:21:00

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;
    }
};

 

...全文
30 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

64,082

社区成员

发帖
与我相关
我的任务
社区描述
学习「 算法 」的捷径就是 「 题海战略 」,社区由「 夜深人静写算法 」作者创建,三年ACM经验,校集训队队长,亚洲区域赛金牌,世界总决赛选手。社区提供系统的训练,答疑解惑,面试经验,大厂内推等机会
社区管理员
  • 英雄哪里出来
  • 芝麻粒儿
  • Amy卜bo皮
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

QQ群:480072171

英雄算法交流 8 群

 

试试用AI创作助手写篇文章吧