【并查集】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;
}
分类:
数据结构【算法题】
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具