并查集模板

并查集模板

主要用于处理一些不相交集合的合并问题,p[i] : i 所在集合的根节点,rank[i] : 以 i 为根节点展开的树的深度。

  • 初始化:各元素自成一个集合,p[i] = i, rank[i] = 0。
  • find(x):找到元素 x 所在的集合的根节点。注意在查找过程中进行路径压缩。
  • union(x, y)(合并):把元素 x 和元素 y 所在的集合合并,要求 x 和 y 所在的集合不相交,如果相交则不合并。合并时候按 rank[x] 和 rank[y] 的大小合并。
/*==================================================*\
 | 带权值的并查集
 | INIT: init(n);
 | CALL: find(x); unin(x, y);
\*==================================================*/
#include<bits/stdc++.h>
using namespace std;

constexpr int N = 10005;
struct lset { 
    int p[N], rank[N], sz; //p[N]:根节点,rank[N]:根节点展开的树的深度
    void link(int x, int y) { 
        if (x == y) 
            return; 
        if (rank[x] > rank[y])  //x深度大于y,则y链到x下。
            p[y] = x; 
        else 
            p[x] = y; 
        if (rank[x] == rank[y]) //如果深度相同且根节点不同,则新的根节点的深度+1
            rank[y]++; 
    } 
    void init(int n) {  //初始化
        sz = n; 
        for (int i = 0;i < sz; i++) { 
            p[i] = i; 
            rank[i] = 0; 
        } 
    } 
    int find(int x) {  
        return x == p[x] ? x : (p[x] = find(p[x])); //将find(p[x])的值(即根)赋给p[x],路径压缩
    } 
    void unin(int x, int y) { 
        link(find(x), find(y)); //合并两个集合,且保存集合根为其中的根节点之一
    } 
    void compress() { 
        for (int i = 0; i < sz; i++) 
            find(i); 
    } 
};

int main(){
    int n, m;
    cin >> n >> m;
    lset t;
    t.init(n+1);
    while (m--) {
        int z, x, y;
        cin >> z >> x >> y;
        if (z == 1) 
            t.unin(x, y);
        else {
            cout << (t.find(x) == t.find(y) ? 'Y' : 'N') << endl;
        }
    }
    return 0;
}

并查集题目链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值