并查集是一种树型的数据结构,用于处理一些不相交集合的合并问题
并查集的主要操作有:
1-合并两个不相交集合
2-判断两个元素是否属于同一个集合
3-路径压缩
并查集的两种优化方法:路径压缩与按秩合并。
int pre[N],rank[N]; //pre[]为前驱,rank[]为当前元素所在集合的大小
//初始化
void Init()
{
for(int i=0; i<N; i++)
{
pre[i] = i;
rank[i] = 1;
}
}
//带路径压缩的非递归找根节点
int Find(int x)
{
int r = x;
while(r != pre[r])
r = pre[r];
int i = x, j;
while(i != r)
{
j = pre[i];
pre[i] = r;
i = j;
}
return r;
}
//带路径压缩的递归找根节点
int Find(int x)
{
if(pre[x] != x)
pre[x] = Find(pre[x]);
return pre[x];
}
//按秩合并,元素少的集合的根节点指向元素多的集合的根节点
void Union(int x,int y)
{
x = Find(x);
y = Find(y);
if(x == y) return;
if(rank[x] >= rank[y])
{
pre[y] = x;
rank[x] += rank[y];
}
else
{
pre[x] = y;
rank[y] += rank[x];
}
}
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1856
题意:给m个集合,求元素最多的那个集合的元素个数。
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1272
题意:给定点集,判断形成它们形成的图是否无环且连通。
分析:先把所有的点的父亲节点指向自己,然后用并查集合并,每次把合并的两个点标记为访问过的,如果中间出现要合并的两个节点的根节点都相同,说明有环,如果最后在访问过的节点中有大于1个节点的父亲节点还是自己,说明不连通。
题目:http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=212
题意:求一个元素所在的集合的所有元素的个数。
分析:直接合并即可。