并查集
来源:互联网 发布:自动顶贴软件 编辑:程序博客网 时间:2024/06/05 15:12
并查集是一种可以方便地进行以下三种操作的数据结构:
合并两个集合;将一元素并入另一集体;判断两个元素是否属于同一个集合。
例如,可以用数组很方便地实现一个并查集,对一个含有n个元素的并查集,可以用一个长度为n的数组实现,主要设计以下四种操作:
初始化并查集:每个元素赋一不同的值,时间复杂度为O(n)。
合并两个集合A和B:将所有标记为B集体的元素的标记变为A集体的标记,时间复杂度为O(n)。
将一元素a并入集合A:时间复杂度为O(1)。
判断两元素是否属于同一集体:只须比较标记,时间复杂度为O(1).
并查集的定义: 并查集是一种简单的集合,它支持三种操作: MakeSet(x):创建一个只包含一个元素x的并查集 Find(x, S):判断x是否在集合S中 Union(A, B):合并两个并查集A和B 并查集与树可以将每一棵树都看成是元素的集合,从而可以用树来表示并查集. 1 4 2 5 6 3 7 MakeSet 一个元素可以看成是只有根结点的树 1 Find 判断一个元素x是否在并查集S中,只需找到x的根结点,看它是否等于S的根结点 1 4 2 5 6 3 7 Union 合并两个并查集,只需把其中一个根结点变成另一个根结点的儿子即可 1 4 2 6 3 用数组表示树 1 4 2 5 6 3 7 5 2 1 1 2 1 0 7 6 5 4 3 2 1 父亲表示法用数组表示森林 1 4 2 5 6 3 7 5 2 0 1 2 0 0 7 6 5 4 3 2 1 父亲表示法并查集常用的数据结构我们一般对所有的元素从1到n编号,这样我们就可以用元素的编号来表示这个元素.同时使用一个数组来存放相应的并查集. 我们用树的根结点来表示整棵树,即整个集合.
类型定义
type AllElements = array [1..MAX] of Integer;
DisjointSet = Integer; {根结点}
MakeSet function MakeSet(x: Integer):DisjointSet;
begin
p[x] := 0; {设p是AllElements类型}
MakeSet := x;
end;
Find function getRoot(x: Integer): Integer;
begin
if p[x] = 0 then getRoot := x
else getRoot := getRoot(p[x]);
end;
function Find(x: Integer; S: DisjointSet):Boolean;
begin
Find := getRoot(x) = s;
end;
Union function Union(A, B: DisjointSet): DisjointSet;
begin
p[B] := A;
Union := A;
end;
时空复杂度分析 O(1) O(h) O(1) 空间复杂度 O(1) O(h) O(1) 时间复杂度 Union Find MakeSet 并查集的路径压缩我们看到,Find的时间复杂度取决于树的高度.在实际中,由于多次Union操作,容易导致树的高度越来越大,从而降低Find的执行效率.
实际上在并查集中,树的具体结构并不重要,只要维持树所包含的结点不变即可(见图,两者所表示的集合等价).因此我们想到在getRoot的同时优化树的结构. 1 4 2 5 6 3 7 1 4 2 5 6 3 7 优化的getRoot function getRoot(x: Integer):Integer; begin if p[x] = 0 then getRoot := x else begin p[x] := getRoot(p[x]); getRoot := p[x]; end; end; 例1 已知有n(<=10000)个国家组成了两大集团,这两大集团之间相互对立.现在提供给你有关情报,请你判断哪些情报是与先前的情报矛盾的. 输入第一行是整数n,接下来若干行每行都是一个情报,由3个数组成.前两个数表示不同的国家,第3个数是0或者1,表示这两个国家是友好的或者对立的.最后一行是3个0表示结束. 对于每行输入,输出Reject表示该行提供的轻薄与前面已知的情报矛盾,否则输出Accept.
例2 你和朋友玩一个游戏.他在纸上写一个长度为n(<=10000)的01串.然后你可以选择任意一段,你的朋友会告诉你这一段里所有数字之和是奇数还是偶数.你怀疑你的朋友作弊,故意告诉你错误的答案.现在你需要用一个程序来帮助你. 输入第一行是整数n,接下来若干行每行包括3个数.前两个数是你所选择的区间,第3个数是0或者1表示这个区间内所有数字之和是偶数还是奇数.最后一行是3个0表示结束. 输出第一个与前面的回答矛盾的答案的编号,如果所有答案都互不矛盾,输出-1.
以下内容为并查集实现的程序代码:
int set[MAXN],rank[MAXN];
int FindSet(int x)
{
if(set[x]!=x)
set[x]=FindSet(set[x]);
return set[x];
}
void MakeSet(int x)
{
set[x]=x;
rank[x]=0;
}
void Link(int a,int b)
{
if(rank[a]>rank[b])
set[b]=a;
else if(rank[a]<rank[b])
set[a]=b;
else
{
set[a]=b;
rank[b]++;
}
}
void Union(int a,int b)
{
Link(FindSet(a),FindSet(b));
}
- HDU3938 并查集 并查集
- 并查集(集并查)
- HDU1232 并查集<并>
- 并查集
- 数据结构-并查集
- 并查集
- 并查集!
- 并查集
- 并查集
- 并查集
- 并查集
- 并查集总结
- 并查集学习
- 并查集
- 并查集
- 并查集
- 所谓并查集
- 并查集
- nyoj,283,对称排序
- Linux基础编程-文件操作open,lseek,read,write,close
- 关于/usr/bin/env
- Android中文语音合成(TTS)
- ios中子线程如何加载图片
- 并查集
- 版本管理
- alert() confirm() prompt() 之用法与区别
- ural 1019 Line Painting (线段树)
- gcc选项
- Java基础知识(1):for/in语句
- SRM 451 div1 (practice)
- Bitmap ---Bitmap.createBitmap函数有6个重载方法
- 目前最快的N皇后问题算法!!!