『并查集』并查集模板

学习并查集前提须知

并查集支持合并查询,针对于查询某两点是否在同一个内,或者将两点之间连一条线。

算法内容

竞赛需要用到的点

1、并查集多用于其他算法的过渡使用,不单独考

2、并查集的思路会多次在以后出现,请理解并查集的每一步思路

并查集略讲

并查集是一个很简单的数据结构,其基本思路围绕着一个就是根节点展开,若有两点的根节点相同那么就肯定在一棵树内,所以我们只需要维护一个点的父亲节点就好了,然后每次询问都查找根节点是否相同。

但这是一种最优的情况,若树退化成链的话,很明显,复杂度高了很多,那就和暴力相同,怎样避免这种情况发生呢?我们上面说到,我们只需要判断两点和根节点的关系,那么我们只保留当前点的根节点关系不就好了?的确,这样就能够满足我们的问题了,这样的优化方式我们叫做路径压缩,且这样就出现了图论中的一种特殊图 菊花图,这种图你以后会遇到,多用于你的算法,在这里这个不是重点,不再赘述。

那么根据上面的信息我们就可以开始写代码了

部分代码展现

起始化

//#define fre yes

#include <cstdio>

const int N = 1000005;
int par[N], Rank[N]; //Rank表示的是秩优化

void init(int n) {
    for (int i = 0; i <= n; i++) {
        par[i] = i;
        Rank[i] = 1;
    }
}

int main() {
    static int n, m;
    ...
    init(n);
    ...
}

合并操作 + 路径压缩 + 秩优化

int find(int x) {
    if(x == par[x]) return x;
    else return par[x] = find(par[x]);
} //路径压缩(与返回父亲节点)

void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if(x == y) return ;
    
    if(Rank[x] <= Rank[y]) par[x] = y;
    else par[y] = x;
    if(Rank[x] == Rank[y]) Rank[x]++;
} //秩优化 与 合并操作

查询操作

int find(int x) {
    if(x == par[x]) return x;
    else return par[x] = find(par[x]);
}

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

所有代码

//#define fre yes

#include <cstdio>

const int N = 200005;
int par[N], Rank[N];

void init(int n) {
    for (int i = 0; i <= n; i++) {
        par[i] = i;
        Rank[i] = 1;
    }
}

int find(int x) {
    if(par[x] == x) return x;
    else return par[x] = find(par[x]);
}

void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if(x == y) return ;

    if(Rank[x] <= Rank[y]) par[x] = y;
    else par[y] = x;
    if(Rank[x] == Rank[y]) Rank[x]++;
}

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

int main() {
    static int n, m;
    scanf("%d %d", &n, &m);
    init(n);
    for (int i = 1; i <= m; i++) {
        int k;
        scanf("%d", &k);
        if(k == 1) {
            int x, y;
            scanf("%d %d", &x, &y);
            unite(x, y);
        } else {
            int x, y;
            scanf("%d %d", &x, &y);
            if(same(x, y)) puts("Y");
            else puts("N");
        }
    } return 0;
}
原文地址:https://www.cnblogs.com/Nicoppa/p/11471383.html