并查集

2024-07-08  本文已影响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};
    }
上一篇 下一篇

猜你喜欢

热点阅读