作用:
1:将两元素合并,
2:访问两元素是否在同一个集合中。
举个例子:
给定2个数1 2;
集合编号分别为1 2;
先查询1与2是否在同一集合,此时1与2不在一个集合;
接下来将1与2所在集合1与集合2合并,集合2-->集合1;
集合编号为1 1;
此时查询1与2是否在同一集合,那1与2都在集合1中。
那么如何实现捏,首先要解决三个问题
问题:1,如何判断根节点:--->if(p[x]==x)
问题:2,如何求x的集合编号:--->while(p[x]==x) x=p[x]
问题:3,如何合并两个集合:将两个集合的根节点合二为一,操作如下:x是集合X的编号;y是集合Y的编号。--->p[x]=y。
基于上述三个问题
给出核心代码
1,初始化,返回x所在集合编号+路径压缩(代码如下)
这里需要简单说明一下路径压缩:
查找某个元素的根的时候,让从此元素到根的路径上的每一个节点都设置根为父节点。
for (int i=1;i<=n;i++) p[i]=i;//初始化节点
int find(int x)//返回x所在集合编号+路径压缩
{
if (p[x]!=x) p[x]=find(p[x]);
return p[x];
}
2,合并操作
if(合并操作条件)
{
p[find(a)]=find(b);
}
3,查询操作
if(查询操作条件)
{
if (find(a)==find(b))//判断两集合所在编号是否相同
puts("Y");
else
puts("N");
}
那我们结合实际题目看一下
原题链接:P3367 【模板】并查集 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
代码如下:
#include <iostream>
using namespace std;
const int N=100010;
int p[N];
int find(int x)//返回x所在集合编号+路径压缩
{
if (p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main()
{
int n, m;
cin>>n>>m;
for (int i=1;i<=n;i++) p[i]=i;//初始化节点
while (m--)
{
int q;//本次操作的操作类型
cin>>q;
int a,b;
cin>>a>>b;
if(q==1)//合并操作(q==1)
{
p[find(a)]=find(b);
}
else//查询操作(q==2)
{
if (find(a)==find(b))//判断两集合所在编号是否相同
puts("Y");
else
puts("N");
}
}
return 0;
}