跳转至

并查集

支持的操作 - 将两个集合合并 - 询问两个元素是否在一个集合中

基本原理: - 每个集合用一颗树来表示 - 树根的编号就是整个集合的编号 - 每个节点存储他的父节点,p[x]表示他的父节点

问题 1. 如何判断树根:if(p[x] == x) 2. 如何求x集合的编号:while(p[x] != x) x = p[x] 3. 如何合并两个集合:p[x]是x的集合编号, p[y]是y的集合编号,令p[x] = y

查询操作

int find(int x){
    if(q[x] != x) q[x] = find(q[x]);
    return q[x];
}

问题2的优化:路径压缩 优化方法:

int find(int x){
    if(q[x] != x) q[x] = find(q[x]);
    return q[x];
}

合并集合

#include <iostream>
using namespace std;
const int N = 100010;
int q[N];

int find(int x){
    if(q[x] != x) q[x] = find(q[x]);
    return q[x];
}

int main(){
    int n, m;
    scanf("%d%d", &n, &m);

    for(int i = 1;i <= n;i++){      //初始化
        q[i] = i;
    }

    char op;
    int a, b;
    while(m--){
        cin >> op;
        switch(op){
            case 'M':
                scanf("%d%d",&a,&b);
                q[find(a)] = find(b);
                break;
            case 'Q':
                scanf("%d%d",&a,&b);
                if(find(a) == find(b)) printf("Yes\n");
                else printf("No\n");
                break;
        }
    }

    return 0;
}

连通块中点的数量

#include <iostream>
using namespace std;
const int N = 100010;
int q[N], sz[N];

int find(int x){
    if(q[x] != x) {
        q[x] = find(q[x]);
    }
    return q[x];
}

int main(){
    int n, m;
    scanf("%d%d", &n, &m);

    for(int i = 1;i <= n;i++){      //初始化
        q[i] = i;
        sz[i] = 1;
    }

    char op[4];
    int a, b;
    while(m--){
        scanf("%s",op);
        if(op[0] == 'Q'){
            if(op[1] == '1'){
                scanf("%d%d", &a, &b);
                if(find(a) == find(b)){
                    printf("Yes\n");
                }
                else{
                    printf("No\n");
                }
            }
            else{
                scanf("%d", &a);
                printf("%d\n",sz[find(a)]);
            }
        }
        else{
            scanf("%d%d",&a,&b);
            if(find(a) == find(b)) continue;
            sz[find(b)] += sz[find(a)];
            q[find(a)] = find(b);
        }
    }

    return 0;
}