并查集

作者: 吾乃零陵上将军邢道荣是也 | 来源:发表于2024-07-08 15:19 被阅读0次

    1,并查集可以解决哪些问题?

    主要就是集合问题,两个节点在不在一个集合,也可以将两个节点添加到一个集合中。

    2,并查集模板

    int n = 1005; // 节点数量3 到 1000
    int[] father = new int[1005];
    
    // 并查集初始化
    void init() {
        for (int i = 0; i < n; ++i) {
            father[i] = i;
        }
    }
    // 并查集里寻根的过程
    int find(int u) {
        return u == father[u] ? u : find(father[u]);
    }
    // 将v->u 这条边加入并查集
    void join(int u, int v) {
        u = find(u);
        v = find(v);
        if (u == v) return ;
        father[v] = u;
    }
    // 判断 u 和 v是否找到同一个根
    boolean same(int u, int v) {
        u = find(u);
        v = find(v);
        return u == v;
    }
    

    以上模板汇总,只要修改 n 和father数组的大小就可以了。

    并查集主要有三个功能。

    1. 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个
    2. 将两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上
    3. 判断两个节点是否在同一个集合,函数:same(int u, int v),就是判断两个节点是不是同一个根节点

    例684 冗余连接

    树可以看成是一个连通且 无环 的 无向 图。

    给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。

    请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的边。

    解:本题的关键在于判断图是否有环。那么我们就可以从前向后遍历每一条边,边的两个节点如果不在同一个集合,就加入集合(即:同一个根节点)。如果边的两个节点已经出现在同一个集合里,说明着边的两个节点已经连在一起了,如果再加入这条边一定就出现环了。

    public int[] findRedundantConnection(int[][] edges) {
            init();
            for (int[] edge:edges){
                int u = edge[0];
                int v = edge[1];
                if (same(u,v))
                    return edge;
                join(u,v);
            }
            return new int[]{-1,-1};
        }
    

    相关文章

      网友评论

          本文标题:并查集

          本文链接:https://www.haomeiwen.com/subject/bffacjtx.html