浅谈Tarjan算法求LCA
来源:互联网 发布:淘宝天猫店有保障吗 编辑:程序博客网 时间:2024/05/21 05:19
Tarjan是一个很厉害的人,不少算法(包括一些数据结构比如splay)都是他发明的…
Tarjan求LCA是利用并查集的思想进行操作的
首先我们有如下的思路
void Tarjan(int u){ fa[u]=u; for(register int i=head[u];i;i=line[i].nxt){ int v=line[i].to; if(v!=father[u]){ Tarjan(v); fa[v]=u; } } for(register int i=head_question[u];i;i=question[i].nxt){ int v=question[i].to; if(!fa[v]) question[i].lca=find(v); }}
如果没有学过Tarjan求LCA的朋友看这里可能会有一些看不懂,现在我来解释一下其中的变量和数组的含义已经算法的大概思路
数据结构讲解:
首先
struct Line{ int val,from,to,nxt;};
以及
struct question{ int from,to,lca,nxt;};
显然这是一个离线算法,也就是说,我需要把所有的处理先离线到结构体中
算法讲解:
现在了解了数据结构之后我们来看看算法的内容以及实现,每次访问到一个数,我们就把其并查集中的fa设置为自己,这与普通并查集的操作是一样的,然后进行向下的访问,只要不往回访问,则往下继续递归操作,回来的时候把v的fa重置为u,也是并查集的操作,表示v可以追溯到u。
对于u的所有子点及子点的子孙已经访问完了之后,我们枚举所有和u有关的询问,试想一张图
假设我们的询问是
P-Q,P-B,A-Q
其中点上的数字是我们访问的
我们发现
而我们当前的
完整代码实现:
void dfs(int u,int fat,int cnt){ father[u]=fat; dfn[u]=++timer; deep[u]=cnt; for(register int i=head[u];i;i=line[i].nxt){ int v=line[i].to; if(v!=fat) dfs(v,u,cnt+line[i].val); }}int find(int x){ return x=fa[x]?x:fa[x]=find(x);} void Tarjan(int u){ fa[u]=u; for(register int i=head[u];i;i=line[i].nxt){ int v=line[i].to; if(v!=father[u]){ Tarjan(v); fa[v]=u; } } for(register int i=head_question[u];i;i=question[i].nxt){ int v=question[i].to; if(!fa[v]) question[i].lca=find(v); }}
值得注意的是,第一个dfs函数中还可以顺便处理一些其他数据,比如说对于一些边有权值的题目,还可以顺便处理一个深度,也就是上述代码中的deep数组所存储的数据
- 浅谈Tarjan算法求LCA
- tarjan算法 离线求LCA
- 浅谈Tarjan——5(用Tarjan求LCA)
- Tarjan离线算法求LCA小结
- tarjan求lca
- tarjan离线求lca
- tarjan求LCA
- 图论--tarjan求lca
- tarjan求LCA
- Tarjan求LCA
- tarjan求LCA笔记
- Tarjan求lca
- Tarjan算法求LCA(最近公共祖先)
- Tarjan离线算法求最近公共祖先(LCA)
- Tarjan离线算法求最近公共祖先(LCA)
- Tarjan离线算法求最近公共祖先(LCA)
- Tarjan算法求LCA(最近公共祖先)
- Tarjan 算法求LCA(Least Common Ancestors)
- 第二章:渠径循究竟,要昼月夜曲
- SYSLINUX引导文件名与菜单解释
- (OK) Android-x86-7.1.1/ kernel 4.4.62
- 05-UI-VFL
- 简单抓站的N种方式-requests与re
- 浅谈Tarjan算法求LCA
- SpringMVC基本配置
- POJ 2517 Cover 笔记
- DS.Lab筆記
- 第四次见习作业
- Android-监听虚拟键盘状态
- 排序算法-----快速排序简单介绍
- D. Okabe and City codeforces 最短路
- 通向架构师的道路(第二十一天)spring(三)之SSH