并查集模板

65 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

路径压缩有两种方式
第一种是在查找的时候压缩(一般都是用这种)
第二种是在合并的时候压缩

模板题:www.acwing.com/problem/con…

#include <iostream>

using namespace std;

const int N = 100010;

int n,m;
int p[N]; // p[x] 存的是x节点的祖宗

int find(int x) // 返回x的祖宗节点 + 路径压缩
{
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++) p[i] = i;
    while(m--)
    {
        char op[2];
        int a,b;
        scanf("%s%d%d",op,&a,&b);
        if(*op == 'M') p[find(b)] = find(a);
        else
        {
            if(find(a) == find(b)) printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}

int parent[1000]; //存储元素的父节点
int Rx[1000]; //秩,相当于高度

int Build(int n) //建立并查集
{
    for(int i = 1; i < n; i++)
    {
        parent[i] = i; //父节点是元素自身
    }
}


int Find1(int x) //查找返回根节点
{
    if(parent[x] != x)
        return Find1(parent[x]);
    return x;
}

int Find2(int x) //查找时路径压缩
{
    if(parent[x] != x) parent[x] = Find2(parent[x]);
  
    return parent[x];
}

void Union1(int x,int y)
{
    parent[Find1(y)] = Find1(x);
}


void Union2(int x,int y) //按秩合并
{
    x = Find1(x);
    y = Find1(y);
    if(Rx[x] < Rx[y])
    {
        parent[x] = y;
    }
    else
    {
        parent[y] = x;
        if(Rx[x] == Rx[y]) Rx[x]++;
    }
}