浅谈Tarjan——5(用Tarjan求LCA)
来源:互联网 发布:Mac怎么改变照片日期 编辑:程序博客网 时间:2024/06/05 21:58
Tarjan算法不仅可以用来缩点,还可以用来求LCA。
先介绍一下LCA,LCA(least common ancestors),是最近公共祖先的英文。指的是在一棵树中,点u和点v的最近的祖先。
如图,以黄点为树根:紫点和黑点的最近公共祖先就是绿点,白点和橙点的最近公共祖先就是橙点,灰点和蓝点的最近公共祖先是黄点。简而言之,LCA就是点u和v的父亲的父亲的父亲……第一个相交的父亲。
LCA的算法有很多,例如倍增RMQ,树剖。用Tarjan算法来求LCA,理论上时间复杂度为(N+Q),但在实际操作中会稍稍慢一些。Tarjan求LCA是一个离线算法,并基于并查集(union-find-set)。
我们用vis记录该点是否被访问过,fa记录该点的父亲,从根节点向下搜索,遍历每一个儿子。如果它的儿子全都遍历完了,就去查询与该点有关的点,也就是所查询的点组中有该点的那些组,如果另一个点v已经被访问过,那么这两个点的最近公共祖先就是find(v),否则先不记录。(证明略)
基本思路就是这五步:
1.从根节点开始搜索。
2.遍历该点u所有子节点v,并标记这些子节点v已被访问过。
3.若是v还有子节点,遍历v的子节点,否则合并u,v。
4.寻找与当前点u有询问关系的点v。
5.若是v已经被访问过了,则可以确认u和v的最近公共祖先为v被合并到的父亲节点a。
伪代码:
void lca(int x){ now[x]=1; for x的所有儿子{ lca(v); vis[v]=1;fa[v]=x; } for 与x有关的查询 if(vis[v]) ans=find(v);}
模板:
void lca(int x){ now[x]=1; for(int i=0;i<f[x].size();i++){ int go=f[x][i]; if(now[go]) continue; lca(go); vis[go]=1;fa[go]=x; } for(int i=0;i<query[x].size();i++){ int go=query[x][i]; if(vis[go]) ans=find(go); }}
详细模拟过程点这里,这位神犇写的很好
阅读全文
0 0
- 浅谈Tarjan——5(用Tarjan求LCA)
- 浅谈Tarjan算法求LCA
- tarjan求lca
- tarjan离线求lca
- tarjan求LCA
- 图论--tarjan求lca
- tarjan求LCA
- Tarjan求LCA
- tarjan求LCA笔记
- Tarjan求lca
- bsoj1375 tarjan离线求lca
- bsoj 2701 tarjan求lca
- 学习笔记:tarjan求lca
- tarjan算法 离线求LCA
- dfs(tarjan)求lca
- 关于Tarjan(3)——离线LCA
- Tarjan LCA
- Tarjan lca
- 剑指offer——面试题51:数组中重复的数字
- Github教程
- 关于数据库原理2
- 关于数据库原理3
- 大话设计模式----模板方法模式
- 浅谈Tarjan——5(用Tarjan求LCA)
- jvm内存结构
- 高级java工程师的64个要求
- DDD与四色原型
- Java学习——修饰符
- 最小生成树的解法
- 第7章 手把手教你学MFC之单文档和多文档
- onkeyup,onkeydown,onkeypress的区别
- hibernate.hbm2ddl.auto配置详解