首先咱们先要知道并查集是什么东西,其实 就是一种树形的数据结构,相当于树,用于处理集合的合并与查询问题。
解决这种问题首先就是进行初始化,这里我们让每一个点都指向自己,初始化并查集的根节点。初始化时,我们将每个节点都视为一个独立的连通分量,因此将每个节点的父节点初始化为自己,即 fa[i] = i。这样在后续的并查集操作中,当两个节点的根节点相同时,就代表它们属于同一个连通分量。代码如下:
for(int i=1;i<=n;i++)
fa[i]=i;
其次就是去寻找根节点,那么,这里使用find函数,主要就是压缩路劲,采用递归,这里话不多说,代码如下:
int find(int x)
{
if(fa[x]==x)
return x;
else fa[x]=find(fa[x]);
return fa[x];
}
之后就是合并和查询,先说合并,先输入再去查询并且保存到变量中,这里就假设输入数据,x和y,然后用a和b保存x与y查询的结果,判断a与b的关系,如果不相等就合并,将b赋值给fa[a],代码如下:
void find(int x,int y)
{
int a=find_f(x),
b=find_f(y);//寻找
if(fx != fy)
{
f[fy] = fx;//合并子集
}
}
以上基本上就是大致内容,好,这里拿一个示例,洛谷p3367,题目要求如果输入z等于1,就将两个所在的集合合并,如果z等于2,就输出是否在同一个集合里面,是的就输出Y,否则输出N。
与上面讲解思路一致,主要代码如下:
while(m--)
{
cin>>z>>x>>y;
a=find(x),b=find(y);
if(z==1)
{
fa[a]=b;
}
else
{
if(a==b)
cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
}
总代码如下:
#include<bits/stdc++.h>
using namespace std;
int fa[200010];int n,m;
int z,x,y;
int a,b;
int find(int x)
{
if(fa[x]==x)
return x;
else fa[x]=find(fa[x]);
return fa[x];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
fa[i]=i;
while(m--)
{
cin>>z>>x>>y;
a=find(x),b=find(y);
if(z==1)
{
fa[a]=b;
}
else
{
if(a==b)
cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
}
return 0;
}