并查集实现Tarjan算法
本文是对http://noalgo.info/476.html的一点理解,特别是对其中
int father[mx]; //节点的父亲
int ancestor[mx]; //已访问节点集合的祖先
这两个数组作用的解释;
首先必须明确,并查集重建的树跟原来的树并不一样;
还是借用该文章的例子:
Tarjan算法是基于DFS(深度优先搜索), 图中的树深度优先遍历的顺序应该是:
->->->->->->->
但作者却说,节点的处理顺序为:
->->->->->->->
其实, 这里第一种顺序是我们处理查询请求的顺序,例如我们遍历到5, 则我们可以获得 5与5之前的所有已经遍历过的节点即(5,4) (5,7)的查询结果;
第二种顺序则是我们建立并查集的顺序
关键代码如下:
void Tarjan(int x) //Tarjan算法求解LCA
{
for (int i = ; i < tree[x].size(); i++)
{
Tarjan(tree[x][i]); //访问子树
unionSet(x, tree[x][i]); //将子树节点与根节点x的集合合并,这里是并查集处理节点x
ancestor[findSet(x)] = x;//合并后的集合的祖先为x
}
vs[x] = ; //标记为已访问, 这里是DFS遍历节点x
for (int i = ; i < query[x].size(); i++) //与根节点x有关的查询
if (vs[query[x][i]]) //如果查询的另一个节点已访问,则输出结果
printf("%d和%d的最近公共祖先为:%d\n", x,
query[x][i], ancestor[findSet(query[x][i])]);
}
两者顺序不同的原因在于下面的第6行和第9行代码,我们在还未遍历父节点的时候,处理第一个子树后,父节点就已经在并查集内了;例如我们还没有遍历节点1,在遍历节点4后,就会处理节点4与其父节点1的合并;
下面,我们来慢慢建立并查集的树;
第一步:
遍历过的元素{4}, 集合[4]{4}->4
第二步:
集合{4}与父节点{1}按秩合并, 合并后的集合为{4,1},集合代表元素为4,即father[4] = 4, father[1] = 4; 集合{4,1}的公共祖先为1,ancestor[4] = 1; 即这个集合的代表元素并不是它的公共祖先
第三步:
遍历过的元素有{4,7}, 有两个集合[4]{4,1}和[7]{7}, ([]里面的元素为代表元素,{}的元素为集合内的所有元素), 此时, 若查询(7,4), 则4已经遍历过, 访问4所在集合的代表元素为 father[4], 集合4的公共祖先为ancestor[father[4]]
第四步:
遍历过的元素有{4,7,5}, 集合[7]{7}合并集合[5]{5}为[7]{7,5}, ancestor[7] = 5
.....
遍历完根节点的第一棵子树后, 集合[7]{4,1,5,7} 与根节点集合[0]{0}合并为[7]{0,1,4,5,7}, 即father[0]=7, 同时更新集合的公共祖先ancestor[7]=0;
最后遍历过的元素{4,7,5,1,2,6,3,0}, 集合为[7]{4,7,5,1,2,6,3,0}, ancestor[7] = 0
为方便理解,最后的图是没有经过路径压缩的, 实际上应该是所有元素的父节点皆为集合代表元素7
并查集实现Tarjan算法的更多相关文章
- upc组队赛14 Communication【并查集+floyd /Tarjan】
Communication 题目描述 The Ministry of Communication has an extremely wonderful message system, designed ...
- 普林斯顿算法(1.3)并查集(union-find算法)——本质就是一个数 下面的子树代表了连在一起的点
转自:https://libhappy.com/2016/03/algs-1.3/ 假设在互联网中有两台计算机需要互相通信,那么该怎么确定它们之间是否已经连接起来还是需要架设新的线路连接这两台计算机. ...
- 最小生成数(并查集)Kruskal算法
并查集:使用并查集可以把每个连通分量看作一个集合,该集合包含连通分量的所有点.这两两连通而具体的连通方式无关紧要,就好比集合中的元素没有先后顺序之分,只有属于和不属于的区别.#define N 100 ...
- hdu5441 并查集+克鲁斯卡尔算法
这题计算 一张图上 能走的 点对有多少个 对于每个限制边权 , 对每条边排序,对每个查询排序 然后边做克鲁斯卡尔算法 的时候变计算就好了 #include <iostream> #inc ...
- Union-Find(并查集): Quick union算法
Quick union算法 Quick union: Java implementation Quick union 性能分析 在最坏的情况下,quick-union的find root操作cost( ...
- Union-Find(并查集): Quick find算法
解决dynamic connectivity的一种算法:Quick find Quick find--Data sturcture 如果两个objects是相连的,则它们有相同的array value ...
- 九度OJ 1024 畅通工程 -- 并查集、贪心算法(最小生成树)
题目地址:http://ac.jobdu.com/problem.php?pid=1024 题目描述: 省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但 ...
- K:Union-Find(并查集)算法
相关介绍: 并查集的相关算法,是我见过的,最为之有趣的算法之一.并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.其相关的实现代码较为简短,实现思想也 ...
- tarjan算法求LCA
tarjan算法求LCA LCA(Least Common Ancestors)的意思是最近公共祖先,即在一棵树中,找出两节点最近的公共祖先. 这里我们使用tarjan算法离线算法解决这个问题. 离线 ...
随机推荐
- 实现表单checkbox获取已选择的值js代码
<input type="checkbox" name="cb" value="1" />aa <input type=& ...
- 使用httpclient提交表单数据加号(+)会被自动替换成空格的坑
坑的场景: 今天使用httpclient-4.5.3版本,发送如下报文: { "idNo": "7+6+0+2ce722a546b39463bd62817fe57f8&q ...
- 机器学习经典书籍&论文
原文地址:http://blog.sina.com.cn/s/blog_7e5f32ff0102vlgj.html 入门书单 1.<数学之美>PDF6 作者吴军大家都很熟悉.以极为通俗的语 ...
- Object.assign() 从一个或多个源对象复制到目标对象
Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. 1.语法: Object.assign(target, ... , sources) 参 ...
- Angular2 直接给元素指定超链接打开会带有 `unsafe` 字样导致数据不能加载
解决方法: 在 component 中引入 import { DomSanitizer } from "@angular/platform-browser";然后在构造函数中注入 ...
- yii2打印数据属性(字段名)/数据
yii2打印数据属性(字段名)/数据 单条数据: $model = $this->findModel($id);//打印字段名 $array = $model->attributes(); ...
- Canvas几种模式的区别
1.screen space-overlay UI显示在最前方 2.screen space-camera 箭头指的是canvas 这样可以放置东西在UI前方和UI后方 3.world space 做 ...
- Windows 10上强制Visual Studio 2017 以管理员身份运行
1. 打开VS的安装目录,找到devenv.exe,右键,选择“兼容性疑难解答”. 2. 选择“疑难解答程序” 3. 选择“该程序需要附加权限” 4. 确认用户帐户控制后,点击测试程序,不然这个对话框 ...
- Python之如何删除pandas DataFrame的某一/几列
删除pandas DataFrame的某一/几列: 方法一:直接del DF['column-name'] 方法二:采用drop方法,有下面三种等价的表达式: 1. DF= DF.drop('co ...
- Python之路day13 web 前端(JavaScript,DOM操作)
参考链接:http://www.cnblogs.com/wupeiqi/articles/5433893.html day13 1. CSS示例 2. JavaScript 3. DOM操作 上节内容 ...