lca---tarjan算法
上面是个草图,特别草
假设现在u = 13号结点,此时按照tarjan算法,2,5,11,12结点作为一类,但是此类的标签不一定是2,所以必须用单独的ancestor指定此类的根结点是2;6号结点单独作为一类,13,17,18作为一类,其他结点都是各自作为一类,如果要求13和11的最近公共结点,只要求11所在类的根结点,即2,以此根结点作为最近公共结点;同理,13与2,5,11,12的最近公共结点都是2(但是现在还不能求出13和2的公共节点,因为2的所有分支还没有遍历完);但是现在还求不出来13和6的公共结点,因为这时vist[6] = 0,所以还不能求;当算法继续运行,回溯至6结点,此时6,13,17,18作为一类,这个类的根结点是6,所以此时就可以求6和13的最近公共结点,就是求出13的根结点(因为这时vist[13] = 1),也就是6;
tarjan算法可以看做后序遍历,只有当前节点u的所有分支都访问完之后,才将vist[u] = 1,表示u已经访问过了。
依次访问当前节点u的所有孩子节点,访问完一个就把这个分支的节点和节点u标注为一类,并且注明这个类的代表就是u;这样依次把u的孩子节点并入以u为代表的类中。
要注意,虽然把u和其孩子节点并入一类,但是在访问完u的所有孩子之前,u还是没有被访问过的。
设当前节点是13, 则13和6的lca不可求,这是因为6的孩子节点还没有访问完,6还是未访问的。
下面是poj1330的代码:
#include <vector>
#include <stdio.h>
#include <cstring>
#include <iostream>
using namespace std;const int MaxNode = 10001;
vector<int> g[MaxNode];
vector<int> q[MaxNode];//用来记录queryint f[MaxNode];
int r[MaxNode];//rank
int indegree[MaxNode];
int ancestor[MaxNode];
bool vist[MaxNode];void Init(int n)
{for (int i=1;i<=n;++i){f[i] = i;//各自为类r[i] = 1;g[i].clear();q[i].clear();}
}void Merge(int a,int b)
{int pa = f[a];int pb = f[b];if (pa!=pb){if (r[pa]>r[pb]){f[pb] = pa;}else//将pa的father变为pb{f[pa] = pb;if (r[pa] == r[pb]){//pb的rank增大++r[pb];}}}
}int Find(int a)
{if(a!=f[a])f[a] = Find(f[a]);return f[a];
}void Tarjan(int u)
{ancestor[u] = u;for (int i=0;i<g[u].size();++i){Tarjan(g[u][i]);Merge(u,g[u][i]);ancestor[Find(u)] = u;//merge之后,类别标签改变,但是必须保证这个类的根节点是u}vist[u] = true;//每当一个节点的所有分支都遍历结束时,就检查与这个节点相连的查询节点for (int i=0;i<q[u].size();++i){if(vist[q[u][i]]){cout<<ancestor[Find(q[u][i])]<<endl;return;}}}int main()
{int Case;scanf("%d",&Case);int ind = 0;for (;ind<Case;++ind){int count;scanf("%d",&count);Init(count);memset(indegree,0,sizeof(indegree));memset(ancestor,0,sizeof(ancestor));memset(vist,0,sizeof(vist));int u,v;for (int i=0;i<count -1;++i){scanf("%d%d",&u,&v);g[u].push_back(v);++indegree[v];}scanf("%d%d",&u,&v);q[u].push_back(v);q[v].push_back(u);for (int i=1;i<=count;++i){if (indegree[i] ==0)//找到树的根节点{Tarjan(i);}}}return 0;
}
Tarjan算法虽然简单,但是很少有资料说的清楚的,下面一段话摘自:http://dongxicheng.org/structure/lca-rmq/
Tarjan算法也要用到深度优先搜索,算法大体流程如下:对于新搜索到的一个结点,首先创建由这个结点构成的集合,再对当前结点的每一个子树进行搜索,每搜索完一棵子树,则可确定子树内的LCA询问都已解决。其他的LCA询问的结果必然在这个子树之外,这时把子树所形成的集合与当前结点的集合合并,并将当前结点设为这个集合的祖先。之后继续搜索下一棵子树,直到当前结点的所有子树搜索完。这时把当前结点也设为已被检查过的,同时可以处理有关当前结点的LCA询问,如果有一个从当前结点到结点v的询问,且v已被检查过,则由于进行的是深度优先搜索,当前结点与v的最近公共祖先一定还没有被检查,而这个最近公共祖先的包涵v的子树一定已经搜索过了,那么这个最近公共祖先一定是v所在集合的祖先。
lca---tarjan算法相关推荐
- 最近公共祖先 LCA Tarjan算法
来自:http://www.cnblogs.com/ylfdrib/archive/2010/11/03/1867901.html 对于一棵有根树,就会有父亲结点,祖先结点,当然最近公共祖先就是这两个 ...
- Tarjan算法_LCA
参考资料:Tarjan算法_LCA tarjan算法求LCA Tarjan 算法&模板 只是对其中的代码进行一下注释,如有错误还得回来再改. //不怕别人比你聪明,就怕别人比你聪明还比你努 ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...
转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...
- LCA 朴素算法+树差分倍增+Tarjan算法 三种算法实现c++代码实现
哔哩哔哩up视频:https://www.bilibili.com/video/BV1nE411L7rz?t=379 转载:http 文章目录 树差分 & 倍增LCA Tarjan 朴素算法 ...
- 【HDU 4547 CD操作】LCA问题 Tarjan算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4547 题意:模拟DOS下的cd命令,给出n个节点的目录树以及m次查询,每个查询包含一个当前目录cur和 ...
- 0x66.图论 - Tarjan算法与无向图连通性
目录 一.无向图的割点与桥 割点 桥/割边 时间戳 搜索树 追溯值 二.割边判定法则 三.割点判定法则 1.luogu P3388 [模板]割点(割顶) 2.luogu P3469 [POI2008] ...
- 『Tarjan算法 无向图的双联通分量』
无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...
- tarjan算法_【朝夕的ACM笔记】树上问题-最近公共祖先-倍增算法
[朝夕的ACM笔记]目录与索引 最近公共祖先-倍增算法 一.基本概念 最近公共祖先问题:对于给定的一颗有根树,求其两个节点的最近公共祖先. 祖先:节点本身.节点的父亲.节点父亲的父亲--都是该节点的祖 ...
- Tarjan算法学习1-双连通
太久不做题,发现很多学过的算法又通通不记得了,或许因为当时既没有深刻理解,也没有及时总结.最近开始复习图论,说是复习,不如说重新学习更加恰当.算法是进入大学紧跟着c语言接触到的第二项"技术& ...
- 【转】BYV--有向图强连通分量的Tarjan算法
转自beyond the void 的博客: https://www.byvoid.com/zhs/blog/scc-tarjan 注:红色为标注部分 [有向图强连通分量] 在有向图G中,如果两个顶点 ...
最新文章
- JS高级程序设计拾遗
- BZOJ2584 : [Wc2012]memory
- 从前到后的CAN总线(一)
- hdu5247找连续数(打表)
- 在SQL2008中清除日志
- Xcode下载安装问题
- 深搜——数字划分问题
- nlp5-n-gram/语言模型(数据平滑方法
- 电子数字计算机最早应用于哪个领域,2013计算机一级B考试模拟试题及答案(2)...
- java计算器流程图_帮帮忙:Java小计算器代码,及需求分析.流程图.
- 【技术博客】基于JsPlumb和JQuery-UI的流程图的保存和再生成
- CSDN-Markdown--基本语法功能效果
- 当子元素用position:relative;时,父元素的overflow:hidden;在ie中失效的解决办法
- truffle serve 发生异常解决办法
- php修改学生信息代码_PHP程序员从入门到佛系第二十八弹:PHP $_POST 变量
- macos 设置黑白打印_如何停止双面打印成为macOS中的默认设置
- 头脑极度开放:前额皮层大战杏仁核
- 20210610 线程数不断飙升问题定位
- python编写自定义函数计算约登值(约登指数、Youden Index)、寻找最佳阈值(threshold、cutoff)、以及最佳阈值对应的ROC曲线中的坐标点
- python编程考试_Python编程练习(一)
热门文章
- 十二、深入Java的循环语句
- Python在window平台打包工具pyinstaller (三十五)
- 五、吃掉Java基本数据类型,学习Java的基础
- 直播预告 | TCCI追问研讨会第二期:双向脑机接口如何实现?
- AAAI 2021 | 幻灯片中文字的重要性预测赛亚军DeepBlueAI团队技术分享
- 百度NeurIPS全球顶会冠军团队,带你7日从零实践强化学习
- 中文数据集有奖公开征集
- 能量视角下的GAN模型(二):GAN=“分析”+“采样”
- CentOS 7 从下载到安装
- vc++ 6.0 创建程序快捷方式的一个例子源码_漏洞复现:phpcms v9.6.0任意文件上传漏洞(CVE201814399)...