并查集
标签: 并查集
- 并查集子节点纸箱父节点
- 判断网络中连接的状态
- 网络是个抽象概念:用户之间形成的网络(好友之间,音乐之间,图书之间,路由器之间,交通网络)
public interface UF {
int getSize() ;
//查看2个元素是否相连的
boolean isConnected (int p,int q);
//将2个元素放在一起
void unionElements(int p,int q);
}
public class UnionFind1 implements UF {
private int[] id;
public UnionFind1(int size){
id =new int[size];
for(int i =0;i<id.length;i++)
id[i] = i;
}
@Override
public int getSize() {
return id.length;
}
@Override
public boolean isConnected(int p, int q) {
return (find(p) ==find(q));
}
@Override
public void unionElements(int p, int q) {
int pId =find(p);
int qId = find(q);
for (int i = 0;i<id.length;i++)
if(id[i] == pId)
id[i] = qId;
}
private int find(int p){
if(p<0 && p>=id.length)
throw new IllegalArgumentException("index out of bound.");
return id[p];
}
}
| unionElements | O(N) |
|---|---|
| isConnected | O(1) |


并查集 通过一个数组去记录 这些节点之间的关系:
举个比较容易理解的例子 假设 向以前抗战时期 中共地下党 之间的间谍他们为了防止中间出现叛徒 即使属于同一个组织 但是也不一定认识 但是每个人 都会有一个联络人 有一个代号 通过暗号交流 要交接任务只能联系上级 只有职位比较高的 才能知道地下和他联系的一级联络人 但是 即便这样 他下级的再下一级很多情况下也是没法知道的 因为地下党也可以自己发展下线而领导可能只知道有这么个人 只能通过一级一级的向上汇报之间的工作。
类比 并查集 也是类似的 数组 有数组索引(代号) 然后数组存储的值 就是别的数组的 索引(代号) a[长江] = 黄河 区别只是 在数组里面索引为 0,1,2,3的顺序数字 做下改变 令 长江为 0 黄河为1 就变成 a[0] = 1 a[1]=xxx
这样就形成了 关系之间的关联 。
public class UnionFind2 implements UF{
private int[] parent;
public UnionFind2(int size){
parent = new int[size];
for (int i=0;i<parent.length;i++){
parent[i] = i;
}
}
@Override
public int getSize() {
return parent.length;
}
private int find(int p){
if(p<0 && p>=parent.length)
throw new IllegalArgumentException("index out of bound.");
//根节点 就是 索引和值都等于自己的 所以 如果索引何止不匹配就去找他的上级 复杂度O(h) h层数
while(p!=parent[p])
p =parent[p];
return p;
}
@Override
public boolean isConnected(int p, int q) {
return find(p)==find(q);
}
@Override
public void unionElements(int p, int q) {
//找到 p最上面的节点
int pRoor =find(p);
//找到 q最上面的节点
int qRoot =find(q);
//如果都在一个领导手下 那就不要合并了
if(pRoor ==qRoot)
return;
//否则p合并到q的领导的下级去
parent[pRoor] = qRoot;
}
}
基于size优化
在合并的时候 看 如果 p的根节点 的数节点 远大于 q 的 根节点 那 向q合并 并 跟新q根节点子节点数量
//用来记录节点下的子节点数量
private int[] sz;
@Override
public void unionElements(int p, int q) {
int pRoor =find(p);
int qRoot =find(q);
if(pRoor ==qRoot)
return;
if(sz[pRoor] <sz[qRoot]){
parent[pRoor] = qRoot;
sz[qRoot] += sz[pRoor];
}else{
parent[qRoot] =pRoor;
sz[pRoor] += sz[qRoot];
}
}
基于rank 优化
private int[] rank;
@Override
public void unionElements(int p, int q) {
int pRoor =find(p);
int qRoot =find(q);
if(rank[pRoor] <rank[qRoot]){
parent[pRoor] =qRoot;
}else if(rank[pRoor] >rank[qRoot])
parent[qRoot] =pRoor;
else{
parent[qRoot] =pRoor;
rank[pRoor] += 1;
}
}
基于路径压缩
parent[p] = parent[parent[p]];
智能推荐
*********(北大)并查集**********
目录 POJ 1703 Find them, Catch them // 种类并查集 自己的详细理解过程 回溯过程 POJ 1611 The Suspects POJ 1988 Cube Stacking POJ 1182 食物链 POJ 1703 Find them, Catch them // 种类并查集 自己的详细理解过程 回溯过程 ...
并查集
并查集是由一群集合构成,最开始时所有元素各自单独构成一个集合。 当集合中只有一个元素时,这个集合的代表节点即为该元素,该元素的father也是自己。 使用哈希表来存并查集中所有集合的所有元素的father信息,记为fatherMap。fatherMap中的一条记录所代表的含义是key节点的father为value节点。每个节点都有father信息。集合代表节点的father为本身。 另外还会存储r...
并查集
并查集(Union-Find) 参考博客 wiki 解决的问题 并查集解决的是一个 连接问题 并查集支持两个操作: union(p,q) 并! 两个节点所在的集合合并 find(p) 查! 查询根节点 回答一个问题: isConneted(p,q) : 两个节点是否连通. 只需给出是否连通. 不需要给出具体路径. 建模思路 对于所有连通的节点. 认为他们是一个组. 因此不连通的节点必然不在同一个组...
并查集
目录 1558.Segment set 1811.Rank of Tetris 1829.A Bug's Life 1198.Farm Irrigation 1558.Segment set A segment and all segments which are connected with it compose a segment set. The size of a segment set ...
查并集
并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了。以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定。不分享出来真是对不起party了。(party:我靠,关我嘛事啊?我跟你很熟么?) 来看一个实例,HDU1232畅通工程 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性问题。比如随意给你两个点,让你判断它们...
猜你喜欢
并查集
太有意思了! 看完绝对会用并查集了; 转载:http://blog.csdn.net/dellaserss/article/details/7724401/ 请看! 讲了并查集和路径压缩算法! 并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了。以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定。不分享出来真是对不起party了。(party:我靠,关我嘛事啊?我跟你很熟么?) 来看...
并查集
并查集:查找 一个元素所属的集合,合并俩个元素所在各自的集合。 查找一个元素所属的集合,就要找到这个元素对应的节点所在的分离集合树; 分离集合树:每个分离集合对应的一棵树 下面是俩颗分离集合树,代表俩个集合 以第一颗树为例,1和3认识,3和4认识,4和2认识,每个元素都是自己的集合,将1合并到3所在的集合,将3合并到4所在的集合,2合并到4的集合,如果找到4的集合是它自己,则这几个元...
查并集
今天来补之前刷过的专题,查并集是一个比较简单的专题:查并集有三种类型,第一种类型是普通查并集,第二个就带权查并集 第三种就是种类查并集 第一种简单查并集主要就是那两个函数: 通过找根节点是否相同,然后再进行合并树。查询他们是否相关的时候就是查询他们的根节点是否相等。 带权并查集:就是通过计算不同顶点到达根节点的距离,然后将他们的差%rand来判断两个顶点之间的关系,sum[i]数组就是...
并查集
并查集(两个优化—按秩合并、路径压缩) 题目背景板 n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 a b 询问a,b是否属于同一集合,是则输出1否则输出0 话说并查集 并查集,并查集,合并 和 查找 集合 请发挥你丰富的想象 1 有一些班级 ,里面...
人工智能基础-数学方法-形式逻辑
1956 年召开的达特茅斯会议宣告了人工智能的诞生。在人工智能的襁褓期,各位奠基者们,包括约翰·麦卡锡、赫伯特·西蒙、马文·明斯基等未来的图灵奖得主,他们的愿景是让“具备抽象思考能力的程序解释合成的物质如何能够拥有人类的心智”。 通俗地说,理想的人工智能应该具备抽象意义上的学习、推理与归纳能力,其通用性将远远强于解决国际象棋或是围棋...
