并查集的实现

并查集的实现

http://www.nowcoder.com/questionTerminal/e7ed657974934a30b2010046536a5372

我以前也不会呀,自从用了并查集之后,嗨,效果还真好!我们全家都用它!——某大佬

关于并查集,有以下题型:

  1. LeetCode130——Surrounded Regions——给了个二维 grid,把里面O全部变成X,但是边界和边界联通区域内的O保留(也能用DFS)
  2. LeetCode261——Graph Valid Tree——给了N个结点和一个边的集合,问这个边的集合能不能构成一棵树
  3. ...

并查集是一种树形数据结构,它由一个整型数组两种操作组成:

  1. 整型数组——记录每一个点对应前导点的下标
  2. find——确定元素属于哪一个子集,可以使用它来确定两个元素是否属于同一个子集
  3. union——将两个子集合并成一个集合

并查集的通用代码(看完你就明白这是个啥玩意儿了):

class UnionFind {
public:
    UnionFind (int sz) {
        pre = vector<int>(sz);
        for (int i = 0; i < sz; ++i) { pre[i] = i; }
    }

    // 查找根节点
    int find(int x) {
        int root = x;
        while (pre[root] != root) {
            root = pre[root];
        }
        // 路径压缩(降低时间复杂度)
        int start = x;
        while(pre[start] != root) {
            int tmp = pre[start];
            pre[start] = root;
            start = tmp;
        }
        return root;
    }

    // 合并子集
    void join(int x, int y) {
        int rootX = find(x), rootY = find(y);
        if (rootX != rootY) pre[rootY] = rootX;
    }

private:
    vector<int> pre;
};

图片如下

图片说明

基于上面👆并查集的框架,稍微修改一下,即可得到本题代码:

//
// Created by jt on 2020/9/7.
//
#include <vector>
#include <iostream>
using namespace std;

class UnionFind {
public:
    UnionFind (int sz) {
        pre = vector<int>(sz+1);
        for (int i = 1; i < sz; ++i) { pre[i] = i; }
    }

    // 查找根节点
    int find(int x) {
        int root = x;
        while (pre[root] != root) {
            root = pre[root];
        }
        // 路径压缩(降低时间复杂度)
        int start = x;
        while(pre[start] != root) {
            int tmp = pre[start];
            pre[start] = root;
            start = tmp;
        }
        return root;
    }

    bool isSameSet(int x, int y) {
        return find(x) == find(y);
    }

    // 合并子集
    void join(int x, int y) {
        int rootX = find(x), rootY = find(y);
        if (rootX != rootY) pre[rootY] = rootX;
    }

private:
    vector<int> pre;
};

int main() {
    int N, M;
    cin >> N >> M;
    UnionFind uf(N);
    for (int i = 0; i < M; ++i) {
        int a, b, c;
        cin >> a >> b >> c;
        if (a == 1) {
            if (uf.isSameSet(b, c)) cout << "Yes" << endl;
            else cout << "No" << endl;
        } else {
            uf.join(b, c);
        }
    }
}
刷遍天下无敌手 文章被收录于专栏

秋招刷题历程

全部评论

相关推荐

我已成为0offer的糕手:别惯着,胆子都是练出来的,这里认怂了,那以后被裁应届被拖工资还敢抗争?
点赞 评论 收藏
分享
诨号无敌鸭:恭喜佬,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务