多学习。

【并查集】AcWing836. 合并集合 —— 并查集入门

并查集

处理问题

1.将两个集合合并
2.询问两个集合是否在一个集合当中

暴力思维

1.询问两个元素是否在一个集合

belong[x] = a; //元素x在a集合
if(belong[x] == belong[y]) //判断a与b是否在一个集合,复杂度O(1)

2.合并集合

//将a,b集合合并为c集合,时间复杂度O(n)
if(belong[x] == a) belong[x] = c;
if(belong[y] == b) belong[y] = c;

并查集可以在近乎O(1)复杂度完成以上两个操作。

基本原理

每个集合用一棵树来表示,树根的编号就是整个集合的编号。每个结点存储它的父节点,p[x]表示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

优化:路径压缩

当我们进行一次查询后,将路途上的所有结点的父亲改为根节点,下次查询即可以O(1)查的根节点

AcWing836. 合并集合

题解

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 1e5 + 10;

string s;
int p[N], n, m, x, y;

int find(int x) //查找集合与路径压缩
{
    if(p[x] != x) return p[x] = find(p[x]);
    return x;
}

int main()
{
    scanf("%d%d",&n, &m);
    for(int i = 1; i <= n; ++i) p[i] = i;
    
    while(m -- )
    {
        cin >> s;
        scanf("%d%d", &x, &y);
        if(s == "M")    p[find(x)] = find(y); //一定要用父节点合并这样才能保证根节点唯一
        else printf("%s\n", find(x) == find(y) ? "Yes":"No");
    }
    
    return 0;
}
posted @   czyaaa  阅读(75)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示