离线快速LCA(最近公共祖先) Tarjan算法
离线快速LCA(最近公共祖先) Tarjan算法
前言
对于 OIer 来说,LCA 一直是处理树上问题的好帮手,无论是倍增还是树剖都有着优秀的 \(\log n\) 的复杂度。不过由于我们(数据规模)的上进,需要更快速求 LCA,于是就有了……
反正之前打死我都不相信这玩意能离线,还能 O(1)
算法思路
首先来一棵树:
我们然后我们将要求 LCA 的点对之间加上一条虚边:
如图,我们将对求点 (7,5)、(8,9)、(11,3) 的 LCA。
一开始每个节点属于一个并查集。
接下来我们通过原树边 DFS 遍历每一个节点,在该节点 \(u\) 的子树遍历完成之后,通过该节点 \(u\) 的虚边遍历与之求 LCA 的节点 \(v\)。
此时如果 \(v\) 已经通过原树边遍历过,那么他们的 LCA 等于 \(v\) 节点的并查集根节点。
反之则不进行任何操作。
然后节点 \(u\) 的并查集祖先设为 \(u\) 在原树上的父亲。
解释一下原理:
当前 \(u\) 子树已经遍历过以后,子树 \(u\) 的并查集根节点的子树 \(t\) 一定还没有遍历完,也就是说此时还在遍历 \(t\) 的子树,如果与节点 \(v\) 要求 LCA 的节点是 \(u\),且此时 \(v\) 通过虚边遍历到了 \(u\)。
不难发现 \((u,v)\) 的公共祖先肯定有 \(t\),而 \(u\) 和 \(v\) 又属于节点 \(t\) 不同的分支,所以 \((u,v)\) 的最近公共祖先就是 \(t\)。
这种通过并查集连接祖先求 LCA 的方法十分巧妙。
CODE
inline void dfs(int u)
{
for(ri i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(vis[v]) continue;
dfs(v);
fa[v]=u;//并查集连向父亲
}
for(pair<int,int> i:EL[u])//遍历虚边
{
if(vis[i.F]) Lca[i.S]=frt(i.F);//frt 求该并查集的根
}
vis[u]=1;//遍历标记
}
//i.F 是节点的编号,i.S 是问题的编号
时间复杂度分析
预处理 \(O(n)\),处理完直接使用 \(O(1)\)。
总时间 \(O(n)\),均摊 \(O(1)\)。
练习
离线快速LCA(最近公共祖先) Tarjan算法的更多相关文章
- LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现
首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵 ...
- LCA 最近公共祖先 tarjan离线 总结 结合3个例题
在网上找了一些对tarjan算法解释较好的文章 并加入了自己的理解 LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通 ...
- HDU 4547 CD操作 (LCA最近公共祖先Tarjan模版)
CD操作 倍增法 https://i.cnblogs.com/EditPosts.aspx?postid=8605845 Time Limit : 10000/5000ms (Java/Other) ...
- LCA最近公共祖先——Tarjan模板
LCA(Lowest Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. Tarjan是一种离线算法,时间复杂度O(n+Q),Q表示询问次数,其中 ...
- LCA最近公共祖先 Tarjan离线算法
学习博客: http://noalgo.info/476.html 讲的很清楚! 对于一颗树,dfs遍历时,先向下遍历,并且用并查集维护当前节点和父节点的集合.这样如果关于当前节点(A)的关联节点( ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)
Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...
- LCA(最近公共祖先)算法
参考博客:https://blog.csdn.net/my_sunshine26/article/details/72717112 首先看一下定义,来自于百度百科 LCA(Lowest Common ...
- LCA 近期公共祖先 小结
LCA 近期公共祖先 小结 以poj 1330为例.对LCA的3种经常使用的算法进行介绍,分别为 1. 离线tarjan 2. 基于倍增法的LCA 3. 基于RMQ的LCA 1. 离线tarjan / ...
- LCA(最近公共祖先)模板
Tarjan版本 /* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000&qu ...
- LCA近期公共祖先
LCA近期公共祖先 该分析转之:http://kmplayer.iteye.com/blog/604518 1,并查集+dfs 对整个树进行深度优先遍历.并在遍历的过程中不断地把一些眼下可能查询到的而 ...
随机推荐
- 玄机蓝队靶场_应急响应_02:apache日志分析
日志分析这块,感觉都是对grep.awk.sort.wc.uniq,这几个命令的使用. 一:靶场 (1)直接cd到linux日志, cd /var/log 发现apache2目录, cd ./apac ...
- cubeide汉化包地址
http://mirrors.ustc.edu.cn/eclipse/technology/babel/update-site 具体步骤看洋桃物联网入门30步的视频
- maven 插件之 maven-shade-plugin,解决同包同名 class 共存问题的神器
开心一刻 有一天螃蟹出门,不小心撞倒了泥鳅泥鳅很生气地说:你是不是瞎啊!螃蟹说:不是啊,我是螃蟹 概述 maven-shade-plugin 官网已经介绍的很详细了,我给大家简单翻译一下 This p ...
- SpringBoot 引入第三方 jar
SpringBoot 引入第三方 jar 项目结构 -BCJS |--lib |--hsm-talos-1.0.1.jar |--src |--pom.xml step1 : 配置第三方 jar 为依 ...
- CSS – Flex
前言 Flex 诞生在 Float 之后, Grid 之前, 它主要是取代 Float 来实现布局. 而它没有 cover 到的地方则由 Grid 弥补. 所以当前, 我们做布局时, 几乎不用 Flo ...
- DQL—查询操作
一.查询语法 select 字段列表 from 表名列表 where 条件列表 group by 分组列表 having 分组后条件 order by 排序字段 limit 分页限定 (提供一个表来操 ...
- (九)Redis 哨兵机制与集群
主从复制中,如果从库发生故障了,客户端可以继续向主库或其他从库发送请求,但是如果主库发生故障了肿么办呢?读请求,那还可以由从库继续提供服务,写请求就么得办法了.此时,哨兵机制就登场了,解决3个问题: ...
- Linux安装miniforge
miniforge 安装 协议条款:bsd-3-clause 支持conda和mamba命令,两者效果一样,推荐使用mamba # Setup Miniforge wget "https:/ ...
- USB 逻辑分析仪分析丢包怎么分析(lecroy USB 逻辑分析仪)
使用 LeCroy USB 逻辑分析仪分析 USB 数据传输中的丢包现象,通常涉及以下步骤: 1. 设置触发条件 在 LeCroy USB 逻辑分析仪中,设置适当的触发条件来捕获数据包丢失的场景.常见 ...
- opengl在编译的过程中,glad使用
我在编译的过程中,遇到:无法找到 -lglad这个错误.最后才发现对于glad的使用不能用-lglad.因为我们通过glad的在线服务可以得到一些文件,其中glad.c文件我们是需要放在我们的项目下面 ...