并查集的几个基本操作图解:
已知上面几个并查级,再来看题
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1050;
int s[maxn];//集
void init_set(){//初始化函数,每一个集位置的大小与元素的大小相同
for(int i=1;i<=maxn;i++)
s[i] = i;
}
int find_set(int x){//查找x归属的关系集
return x==s[x]? x:find_set(s[x]);//如果x的归属集是本身,则返回x。也就是说当前变量x没有和任何变量产生关系
//否则继续查找当前x归属的集A的母集B
}
void union_set(int x,int y)//合并关系集
{
x = find_set(x);//首先找到x与y对应的最终母集
y = find_set(y);
if(x!=y)s[x]=s[y];//如果两个不是同一个母集,那么就将y的母集给到x的母集(也就是x和y建立关系s[y])
}
int main()
{
int t,n,m,x,y;
cin>>t;
while(t--)
{
cin>>n>>m;
init_set();
for(int i=1;i<=m;i++)
{
cin>>x>>y;
union_set(x,y);//根据输入的关系,建立关系
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(s[i]==i)//如果元素和最终归属集相同,则桌子数加1。
ans++;
}
cout<<ans<<endl;
//桌子的数量取决于大家是否认识,也就是说桌子坐的人要么是一个人,要么是归属于同一个母集的所有人
}
return 0;
}
关于算法优化:
合并优化不是特别明白,粘贴于此待复习时看
路径压缩就像是记忆性递归,减少递归深度。