并查集是一种树型的数据结构,用于处理一些不相交集合的合并问题
并查集的主要操作有:
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
题意:求一个元素所在的集合的所有元素的个数。
分析:直接合并即可。