《五月集训》(第二十六天)——并查集

前言

        欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
        今天是五月集训第二十六天:并查集🔥🔥🔥🔥

一、练习题目

        990. 等式方程的可满足性
        1319. 连通网络的操作次数
        886. 可能的二分法

二、算法思路

  • 1、990. 等式方程的可满足性:学完并查集再来做,理解思路是不难的。
  • 2、1319. 连通网络的操作次数:并查集使用
  • 3、886. 可能的二分法:这道题还不大会😢

三、源码剖析

// 990. 等式方程的可满足性
class Solution {
    #define maxn 256
    int f[maxn];
    void unionfind_init() {
        for(int i = 0; i < maxn; ++i) {
            f[i] = i;
        }
    } //(1)

    int unionfind_find(int x) {
        return f[x] == x ? x : (f[x] = unionfind_find(f[x]));
    } //(2)

    bool unionfind_union(int x, int y) {
        int fx = unionfind_find(x);
        int fy = unionfind_find(y);
        if(fx == fy) {
            return false;
        }
        f[fx] = fy;
        return true;
    } //(3)
public:
    bool equationsPossible(vector<string>& equations) {
        unionfind_init();
        for(int i = 0; i < equations.size(); ++i) {
            if(equations[i][1] == '=') {
                unionfind_union(equations[i][0], equations[i][3]);
            }
        } //(4)
        for(int i = 0; i < equations.size(); ++i) {
            if(equations[i][1] == '!') {
                if(unionfind_find(equations[i][0]) == unionfind_find(equations[i][3])) {
                    return false;
                }
            }
        } //(5)
        return true;
    }
};
  • 1、并查集在用之前需要初始化,可以理解为各大门派自己就是一个老大;
  • 2、这个函数用于并查集的查找,递归的找到父节点是哪一个;
  • 3、这个函数用于判断是不是同一类,不是同一类的话,我们把它归为同一类,你得认我是老大。
  • 4、先判断集合相等的,我们把它归为一类;
  • 5、判断不相等的情况,如果前面已经归为一类了,矛盾了,这不是互相不服输了吗。
// 1319. 连通网络的操作次数
class Solution {
    #define maxn 100010
    int f[maxn];
    void unionfind_init() {
        for(int i = 0; i < maxn; ++i) {
            f[i] = i;
        }
    }

    int unionfind_find(int x) {
        return f[x] == x ? x : (f[x] = unionfind_find(f[x]));
    }

    bool unionfind_union(int x, int y) {
        int fx = unionfind_find(x);
        int fy = unionfind_find(y);
        if(fx == fy) {
            return false;
        }
        f[fx] = fy;
        return true;
    } //(1)
public:
    int makeConnected(int n, vector<vector<int>>& connections) {
        int edge = 0, count = 0;
        int hash[maxn];
        unionfind_init();
        for(int i = 0; i < connections.size(); ++i) {
            int a = connections[i][0];
            int b = connections[i][1];
            if(!unionfind_union(a, b)) {
                ++edge;
            } //(2)
        }
            memset(hash, 0, sizeof(hash));
            for(int i = 0; i < n; ++i) {
                int setld = unionfind_find(i);
                if(!hash[setld]) {
                    hash[setld] = 1;
                    ++count;
                } //(3)
            }
            if(edge >= count - 1) {
                return count - 1; //(4)
            }
        return -1;
    }
};
  • 1、并查集的构建是和上一题一样的;
  • 2、构造连通分量并统计边数;
  • 3、统计连通分量的数目;
  • 4、连接n个分量需要n-1条边,如果满足则返回cnt - 1。
// 886. 可能的二分法
  • 1、
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值