当前位置:文档之家› acm培训资料——树与等价问题

acm培训资料——树与等价问题

如P143图6.21
int fix_mfset( MFSet &S, int i){
if(i<1||i>S.n) return -1;
for(j=i;S.nodes[j].parent>0;j=S.nodes[j].parent);
for(k=i;k!=j;k=t){
t=S.nodes[k].parent;
当所有的m个关系处理完后,剩下的这些非空子 集即为S的R等价类。
6.5 树与等价问题
划分等价类需对集合进行的三个基本操作: 构造只含一个元素的集合 判定某个元素所在的子集 合并两个互不相交的集合
约定: 利用树型结构表示集合,每个节点表示集合的元
素 根节点的成员兼作子集的名称
6.5 树与等价问题
}
return OK; }// mix_mfset
深度不超过┗ log2n+1 ┛
6.5 树与等价问题
一个实例
假设集合S={x|1≤x ≤n是正整数},R是S上的 一个等价关系。
R={(1,2),(3,4),(5,6),(7,8),(1,3),(5,7),(1,5),…} 求S的等价类
1 2 3 4 5 6 7 8…n
if( S.nodes[i].parent>S.nodes[j].parent){
S.nodes[j].parent+=S.nodes[i].parent;
S.nodes[i].parent=j;
}else{
S.nodes[i].parent+=S.nodes[j].parent;
S.nodes[j].parent=i;
n
1 2 3 ... n
3
3
2
2 ... 2
1
1
16.5 树与等价问题改进“并”操作的算法,令成员少的子集树根节点指向成员多的子集的 根;修改存储结构—令根节点的parent与存储子集中所含成员数目的负
值St。atus mix_mfset( MFSet &S, int i, int j){
if(i<1||i>S.n||j<1||j>S.n) return ERROR;
-1 -1 -1 -1 -1 -1 -1 -1
-1
处理(1,2),(3,4),(5,6),(7,8)之后
1 2 3 4 5 6 7 8…n
-2 1 -2 3 -2 5 -2 7
-1
6.5 树与等价问题
一个实例
假设集合S={x|1≤x ≤n是正整数},R是S上的 一个等价关系。
R={(1,2),(3,4),(5,6),(7,8),(1,3),(5,7),(1,5),…} 求S的等价类
}// merge_mfset
O( 1)
6.5 树与等价问题
上述实现对于这样的例子:
假设n个集合S1,S2,…,Sn, 每个子集只有一个元素Si={i}, 用n棵只有一个根节点的树表示,做n-1次并操作后, 最后得到的集合的深度为n,加上每次进行查找成员 “1”所在子集的操作,全部操作时间是O(n2)。
(x,y ∈ S)的等价偶对确定了等价关系R,求S 的划分。
6.5 树与等价问题
确定等价类的算法:
令S中每个元素各自形成一个只含单个成员的子集, 记作S1,S2,…,Sn
重复读入m个关系(偶对),对每个读入的偶对 (x,y),判定x和y所属的子集,若这两个子集不相等, 则合并它们并取代这两个子集
6.5 树与等价问题
离散数学中的概念: 集合S上的关系R定义为SxS的一个子集。 等价关系是具有自反、传递、对称的关系。 若R是S上的等价关系,由R可以产生这个集合S的
一个唯一的划分S1,S2…,这些集合互不相交,其并 为S,分别属于不同的等价类。
6.5 树与等价问题
确定等价类的问题 假设集合S有n个元素,已知m个形如(x,y)
}// find_mfset
O( d) d—树的深度
Status merge_mfset( MFSet &s, int i, int j){ //集合的并 if( i<1||i>S.n||j<1||j>S.n) return ERROR; S.nodes[i].parent=j; return OK;
1 2 3 4 5 6 7 8…n
-4 1 1 3 -4 5 5 7
-1
处理(1,5)之后
1 2 3 4 5 6 7 8…n
-8 1 1 3 1 5 5 7
-1
6.5 树与等价问题
改进查找子集算法,增加“压缩路径”功能。当所查元素i不 在树的第二层时,在算法中增加一个“压缩路径”的功能, 即将所有从根到元素i路径上的元素都变成树根的孩子。
1 2 3 4 5 6 7 8…n
-2 1 -2 3 -2 5 -2 7
-1
处理(1,3),(5,7)之后
1 2 3 4 5 6 7 8…n
-4 1 1 3 -4 5 5 7
-1
6.5 树与等价问题
一个实例
假设集合S={x|1≤x ≤n是正整数},R是S上的 一个等价关系。
R={(1,2),(3,4),(5,6),(7,8),(1,3),(5,7),(1,5),…} 求S的等价类
集合的表示 用代树表Ti表每示个每元个素子,集每S棵i,树森的林根F节表点示同集时合S用,来每表个示节子点
集Si
两种关键的基本操作:查找某个元素是否属于某个 集合,合并两个集合。采用何种树、森林的存储 方式可以有效地实现这些基本操作?
集合的并:将一子树的根指向另一子树的根即可 是否属于集合:从该节点出发,逐级查找父节点到
S.nodes[k].parent=j; 经过这些改进后,划分等价类的时间
}
复杂度为O(nα(n)),其中α(n)≤4
return j;
}// fix_mfset
根节点为止。
6.5 树与等价问题
typedef PTree MFSet;
int find_mfset( MFSet S, int i){ //查找i所属子集 if( i<1 || i>S.n) return -1; for( j=i; S.nodes[j].parent>0; j=S.nodes[j].parent); return j;
相关主题