议题:并查集(Union-Find Sets)

分析:

  • 一种树型数据结构,用于处理不相交集合(Disjoint Sets)的合并以及查询;一开始让所有元素独立成树,也就是只有根节点的树;然后根据需要将关联的元素(树)进行合并;合并的方式仅仅是将一棵树最原始的节点的父亲索引指向另一棵树;

  • 优化:加入一个rank数组存储节点深度的下界(从当前节点到其最远子节点的距离),从而可以启发式的对树进行合并,从而减少树的深度,防止树的退化;使 得包含较少节点的树根指向包含较多节点的树根,具体指代为树的高度;另一个优化就是路径压缩,尽可能将子节点都直接连接到根节点之后;

  • 并查集的空间复杂度为O(N),构建一个集合的时间复杂度为O(N);压缩后的查找复杂度是一个很小的常数;应用:Kruskal算法求最小生成树中判断新加入的边是否在同一棵树内部;两个节点的最近公共祖先(Least Common Ancestors);

  • 初始化father:各个节点独立成树,并且其father[i]=i,也就是其父节点就是其自身;

    father[i]
    0 1 2 3 4 5 6 7 8 9
    0 1 2 3 4 5 6 7 8 9

    初始化rank:各个节点为根节点,所以高度都为1;
    rank[i]
    0 1 2 3 4 5 6 7 8 9
    1 1 1 1 1 1 1 1 1 1

    合并2和6:由于rank[2]=rank[6],所以将2的父亲索引指向6,这样2和6就在同一棵树;并需将6的rank值增加1;
    father[i]
    0 1 2 3 4 5 6 7 8 9
    0 1 6 3 4 5 6 7 8 9
    rank[i]
    0 1 2 3 4 5 6 7 8 9
    1 1 1 1 1 1 2 1 1 1

样例:

 int *father;
int *rank; /**
* 并查集的初始化:
* 数组father中的元素在最开始ide时候都是独立的树,也就是只有根节点
* 的树,数组father的下标i表示节点,而father[i]的值表示i节点的父亲
* 节点;rank[i]=1表示一开始所有树节点的高度都为1
* */
void init(int cap) {
father=new int[cap];
rank=new int[cap];
/**
* 时间复杂度为O(N)
* */
for(int i=;i<;i++) {
father[i]=i;
rank[i]=;
}
} void clean() {
delete [] father;
delete [] rank;
}
/**
* 查找元素所在的集合并进行路劲压缩:
* 由于需要频繁使用GetFather()函数,并且其时间复杂度受树结构影响;
* 当元素较多的时候,集合退化成链表,则GetFather()需要O(N),所以
* 需要对其进行优化,每次调用GetFather()的时候都将输入元素压缩成
* 最原始父亲节点的直接子节点
* */
int GetFather(int son) {
if(father[son]==son)
return son;
else {
father[son]=GetFather(father[son]);
return father[son];
}
} /**
* 合并两个不相交的集合:
* 输入元素x和y来自两个不相交的集合,找到其最原始的父亲节点
* 并将一个原始父亲节点设置为另一个原始父亲节点的父亲节点
* */
void Union1(int x, int y) {
/**
* GetFather()为递归寻找输入节点的最原始的父亲节点
* */
int fx=GetFather(x);
int fy=GetFather(y);
/**
* 判断x和y是否来自同一棵树,如果不是才进行赋值;其实可以
* 不同进行判断(省去if语句)
* 注意最原始父亲节点的father[i]=i;
* */
if(fx!=fy)
father[fx]=fy;
} /**
* 利用rank加权数组启发式进行合并
* */
void Union2(int x, int y) {
int fx=GetFather(x);
int fy=GetFather(y); if(fx==fy) return;
/**
* rank[fx]较大,说明其越靠近根节点,则将
* fy连接到其后面可以压缩路径
* */
if(rank[fx]>rank[fy])
father[fy]=fx;
else {
if(rank[fx]==rank[fy])
rank[fy]++;
father[fx]=fy;
}
} /**
* 判断两个元素是否属于同一个集合:
* 利用GetFather()函数判断其最原始父亲节点是否相同
* */
bool IsSameSet(int x, int y) {
return GetFather(x)==GetFather(y);
}

笔试算法题(38):并查集(Union-Find Sets)的更多相关文章

  1. 并查集(Union/Find)模板及详解

    概念: 并查集是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有求连通子图.求最小生成树的Kruskal 算法和求最近公共祖先等. 操作: 并查集的基本操作有两个 ...

  2. hdu 4641 K-string SAM的O(n^2)算法 以及 SAM+并查集优化

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4641 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末 ...

  3. hdu 1233(还是畅通project)(prime算法,克鲁斯卡尔算法)(并查集,最小生成树)

    还是畅通project Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  4. 前端如何应对笔试算法题?(用node编程)

    用nodeJs写算法题 咱们前端使用算法的地方不多,但是为了校招笔试,不得不针对算法题去练习呀! 好不容易下定决心 攻克算法题.发现js并不能像c语言一样自建输入输出流.只能回去学习c语言了吗?其实不 ...

  5. PAT甲题题解-1107. Social Clusters (30)-PAT甲级真题(并查集)

    题意:有n个人,每个人有k个爱好,如果两个人有某个爱好相同,他们就处于同一个集合.问总共有多少个集合,以及每个集合有多少人,并按从大到小输出. 很明显,采用并查集.vis[k]标记爱好k第一次出现的人 ...

  6. POJ 2421 Constructing Roads (Kruskal算法+压缩路径并查集 )

    Constructing Roads Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 19884   Accepted: 83 ...

  7. 笔试算法题(50):简介 - 广度优先 & 深度优先 & 最小生成树算法

    广度优先搜索&深度优先搜索(Breadth First Search & Depth First Search) BFS优缺点: 同一层的所有节点都会加入队列,所以耗用大量空间: 仅能 ...

  8. [Comet OJ - Contest #6 D][48D 2280]另一道树题_并查集

    另一道树题 题目大意: 数据范围: 题解: 这个题第一眼能发现的是,我们的答案分成两种情况. 第一种是在非根节点汇合,第二种是在根节点汇合. 尝试枚举在第几回合结束,假设在第$i$回合结束的方案数为$ ...

  9. hdu 4641K-string SAM的O(n^2)算法 以及 SAM+并查集优化

    转载:http://www.cnblogs.com/hxer/p/5675149.html 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末尾插入一 ...

随机推荐

  1. 关于loadrunner运行场景时提示“初始化失败,通信错误”的解决方案

    1)在loadrunner的安装目录下的bin文件夹下有个“wlrun.exe”的文件 2)右键点击“属性”->"兼容性"->兼容模式中选择“windows xp(se ...

  2. vs2010 每行代码显示虚线

    快捷键:Ctrl+R,W或Ctrl+E,S,即可去除 或者是编辑菜单——高级——查看空白 VS12010代码编辑器横向滚动条 工具----选项-----文本编辑器---所有语言---右侧 自动换行去掉

  3. bzoj 2456: mode【瞎搞】

    这题加个#include都会MLE-- 神思路,每个数抵消宇哥和它不同的数,最后剩下的就是众数 #include<cstdio> int n,la,x,tot; int main() { ...

  4. bzoj 3751: [NOIP2014]解方程【数学】

    --我真是太非了,自己搞了7个质数都WA,从别人那粘5个质数就A了-- 就是直接枚举解,用裴蜀定理计算是否符合要求,因为这里显然结果很大,所以我们对多个质数取模看最后是不是都为0 #include&l ...

  5. X86 Linux 下 SIGBUS 总结

    SIGBUS 在 x86 Linux 上并不多见,但一旦出现,其调用堆栈常常让人摸不着头脑,加之信号问题各平台系统间差异较大,更让人难以理清,这里稍微总结一下 x86 Linux 上大概有哪些情形会触 ...

  6. JAVA启动参数三:非Stable参数

    前面我们提到用-XX作为前缀的参数列表在jvm中可能是不健壮的,SUN也不推荐使用,后续可能会在没有通知的情况下就直接取消了:但是由于这些参数中的确有很多是对我们很有用的,比如我们经常会见到的-XX: ...

  7. [POI2008]海报PLA

    Description N个矩形,排成一排. 现在希望用尽量少的矩形海报Cover住它们. Input 第一行给出数字N,代表有N个矩形.N在[1,250000] 下面N行,每行给出矩形的长与宽.其值 ...

  8. bzoj2002 [Hnoi2010]Bounce 弹飞绵羊【分块】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 这一题除了LCT解法,还有一种更巧妙,代码量更少的解法,就是分块.先想,如果仅仅记录每 ...

  9. 四大开源协议比较:BSD、Apache、GPL、LGPL【转载】

    四大开源协议原文链接 本文参考文献:http://www.fsf.org/licensing/licenses/ 现今存在的开源协议很多,而经过Open Source Initiative组织通过批准 ...

  10. overlaps the location of another project Zendstudio导入已经存在的目录

    转 http://blog.csdn.net/kdchxue/article/details/50633745 最近弄zendstuido导入已经存在的项目,找了很多地方终于找到了导入的方法,特别记录 ...