[关闭]
@Lilacy 2015-07-25T10:09:49.000000Z 字数 1077 阅读 1130

并查集

概念

并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。(维基百科)

并查集一般有三个操作

  • 1.初始化(init)
  • 2.查询(Find)
  • 3.合并(Union)

1. 初始化

我们用 par 数组表示i结点的父亲,rank数组表示树的高度,当par[x] = x 时,x就是所在树的根,因为刚开始没有边,每个结点就是自己的根。

  1. void init(int n)
  2. {
  3. for(int i = 0; i < n; i++)
  4. {
  5. par[i] = i;
  6. rank[i] = 0;
  7. }
  8. }

2. 查询

查询树的根
写法1(递归)

  1. int find( int x)
  2. {
  3. if(par[x] == x)
  4. return x;
  5. else
  6. return par[x] = find( par[x]);//路径压缩
  7. }

写法2

  1. int find(int x)
  2. {
  3. int root, temp;
  4. root = x;
  5. while(root != par[root])//查找位置
  6. root = par[root];
  7. while(x != root)//路径压缩
  8. {
  9. temp = par[x];
  10. par[temp] = root;
  11. x = temp;
  12. }
  13. return root;
  14. }

3.合并

  1. void union(int x,int y)//合并x,y所在集合
  2. {
  3. x = find(x);
  4. y = find(y);
  5. if(x == y)//判断x,y是否属于同一集合
  6. return ;
  7. //防止树退化(辉哥说用了很多年从来发现有明显优化的现象发生。。。)
  8. if(rank[x] < rank[y])
  9. par[x] = y;
  10. else
  11. {
  12. par[y] = x;
  13. if(rank[x] == rank[y])
  14. rank[x]++;
  15. }
  16. }

并查集全家桶

例题1 poj 1182 食物链

题意:
有三种关系 A吃B B吃C C吃A
有N个动物 编号1~N,属于A B C的一类。1<=N<=50000
给出两种信息共K条 0<=K<=100000
1.x,y同类
2.x 吃 y
请你判断说假话的总数。

例题2 poj 1611 The Suspects

题意:0号学生染病,有n个学生(0到n-1),m个小组。和0号学生同组的学生染病,病可以传染。
输入格式:n,m
数量 学生编号(m行)

例题3 poj 1988 Cube Stacking

题意:n个方块(n<=30000),p组操作(p<=100000),操作有两种,M a b 将含有a的堆放在包含b的堆上,还有一种是 C a统计a下面有多少个方块

思路:带权并查集,一堆中最顶上的方块作为父节点,用dist[X] 统计X到父亲节点的距离,rank[par[X]]表示团的大小,两者相减即为答案

并查集的应用

1.Krusakal算法中加边时判断边的两点是不是在同一个连通分量上
2.判环

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注