代码随想录| 图论04 查并集 ●查并集理论知识 ●1971.寻找图中是否存在路径 ●684.冗余连接 ●685.冗余连接II

#查并集理论知识

并查集用处:解决连通性问题

  • 将两个元素添加到一个集合中。
  • 判断两个元素在不在同一个集合

思路:将三个元素A,B,C (分别是数字)放在同一个集合,其实就是将三个元素连通在一起,如何连通:只需要用一个一维数组来表示,即:father[A] = B,father[B] = C 这样就表述 A 与 B 与 C连通了(有向连通图)。如果几个元素的根是同一个,代表在同一集合。

find的路径压缩:

代码随想录| 图论04 查并集 ●查并集理论知识 ●1971.寻找图中是否存在路径 ●684.冗余连接 ●685.冗余连接II_第1张图片

代码随想录| 图论04 查并集 ●查并集理论知识 ●1971.寻找图中是否存在路径 ●684.冗余连接 ●685.冗余连接II_第2张图片

就需要 路径压缩,将非根节点的所有节点直接指向根节点

代码随想录| 图论04 查并集 ●查并集理论知识 ●1971.寻找图中是否存在路径 ●684.冗余连接 ●685.冗余连接II_第3张图片 

路径压缩长一点写:

int find(int u) {
    if (u == father[u]) return u;
    else return father[u] = find(father[u]); // 路径压缩
}

 路径压缩短一点写:

int find(int u) {
    return u == father[u] ? u : father[u] = find(father[u]);
}

 随想录的查并集模板:

int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好
vector father = vector (n, 0); // C++里的一种数组结构

// 并查集初始化
void init() {
    for (int i = 0; i < n; ++i) {
        father[i] = i;
    }
}
// 并查集里寻根的过程
int find(int u) {
    return u == father[u] ? u : father[u] = find(father[u]); // 路径压缩
}

// 判断 u 和 v是否找到同一个根
bool isSame(int u, int v) {
    u = find(u);
    v = find(v);
    return u == v;
}

// 将v->u 这条边加入并查集
void join(int u, int v) {
    u = find(u); // 寻找u的根
    v = find(v); // 寻找v的根
    if (u == v) return ; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回
    father[v] = u;
}

你可能感兴趣的:(c++,leetcode,算法,图论)