本文章原创作者为:ACdreamers。我对其进行了补充。
并查集是一种树型的数据结构,用于处理一些不相交集合的合并问题
并查集的主要操作有:
1-合并两个不相交集合
2-判断两个元素是否属于同一个集合
3-路径压缩
并查集的两种优化方法:路径压缩与按秩合并。
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1856
题意:给m个集合,求元素最多的那个集合的元素个数。
参考代码:
# include<cstdio>
# include<cstring>
# include<iostream>
using namespace std;
int ans[10000005];
int sum[10000005];
int Find(int x)
{
int r = x;
while(r != ans[r])
r = ans[r];
int i = x, j;
while(i != r)
{
j = ans[i];
ans[i] = r;
i = j;
}
return r;
}
int main()
{
int n,i,a,b,num;
while(scanf("%d",&n)!=EOF)
{
num=1;
for(i=1; i<=10000000; i++)
{
ans[i]=i;
sum[i]=1;
}
for(i=0; i<n; i++)
{
scanf("%d%d",&a,&b);
a=Find(a);
b=Find(b);
if(a!=b)
{
if(sum[a]<=sum[b])
{
ans[a]=b;
sum[b]=sum[a]+sum[b];
if(sum[b]>num) num=sum[b];
}
else
{
ans[b]=a;
sum[a]=sum[a]+sum[b];
if(sum[a]>num) num=sum[a];
}
}
}
printf("%d\n",num);
}
return 0;
}
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1272
题意:给定点集,要判断是否任意两点只有一条路径,如果直接用枚举任意两点,再判断是否有两条路径理论上是可以的,但是计算量太大,超时。只需判断形成它们形成的图是否无环且连通。
分析:先把所有的点的父亲节点指向自己,然后用并查集合并,每次把合并的两个点标记为访问过的,如果中间出现要合并的两个节点的根节点都相同,说明有环,如果最后在访问过的节点中有大于1个节点的父亲节点还是自己,说明不连通。
题目:http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=212
题意:求一个元素所在的集合的所有元素的个数。
分析:直接合并即可。