离线快速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 对整个树进行深度优先遍历.并在遍历的过程中不断地把一些眼下可能查询到的而 ...
随机推荐
- 阿里云 SLS 模糊查询日志
查询包含test前缀的词 1. 访问 https://sls.console.aliyun.com/lognext/profile 2. 在Project列表中找到对应的sls日志Project 3. ...
- 【YashanDB知识库】ycm纳管主机安装YCM-AGENT时报错“任务提交失败,无法连接主机”
问题现象 执行安装ycm-agent命令纳管主机时报错 问题的风险及影响 会导致ycm-agent纳管不成功,YCM无法监控主机和数据库 问题影响的版本 yashandb-cloud-manager- ...
- CSS – Flex
前言 Flex 诞生在 Float 之后, Grid 之前, 它主要是取代 Float 来实现布局. 而它没有 cover 到的地方则由 Grid 弥补. 所以当前, 我们做布局时, 几乎不用 Flo ...
- Go 学习路线图
基础阶段 学习内容: 掌握 Go 的基本语法,包括变量.常量.数据类型(如整数.浮点数.字符串.布尔值.数组.切片.映射等).运算符等. 理解程序的控制流,如条件语句(if-else.switch-c ...
- USB协议详解第8讲(USB描述符-字符串和语言ID描述符)
1.字符串描述符相关概念 字符串描述符:首先,字符串描述符就是用字符串描述一个设备的一些属性,毕竟人能看懂的是字符,而不是十六进制,描述的属性包括设备厂商名字.产品名字.产品序列号.各个配置名字.各个 ...
- USB PD和USB TYPE-C 的区别
USB Power Delivery (USB PD) 和 USB Type-C 是两个不同但相关的技术标准,它们在功能和应用上有所区别. 1. USB Type-C 连接器标准: USB Type- ...
- [Vue warn]: Error in v-on handler (Promise/async): "TypeError: Object(...) is not a function"
引用外部发文件时候,只是部分引用,所以原本是解构方式引用的,我忘记加{ }了
- 现在 Llama 具备视觉能力并可以在你的设备上运行 - 欢迎使用 Llama 3.2
Llama 3.2 来了!今天,我们欢迎 Llama 系列的下一个版本加入 Hugging Face.这次,我们很高兴与 Meta 合作发布多模态和小型模型.在 Hub 上提供了十个开源模型 (5 个 ...
- 报名开启|QKE 容器引擎托管版暨容器生态发布会!
当下,"云原生"技术红利正吞噬旧秩序,重塑新世界. 但您的企业是否依然困惑:缺少运维人员或运维团队,想要专注于业务的开发,又不得不兼顾集群的日常运维:在生产环境中,为了保证业务的高 ...
- Mongo oplog理解
转载请注明出处: oplog(操作日志)是MongoDB中用于记录所有写操作的日志.它是一个特殊的集合,存储在副本集的主节点中.oplog用于确保副本集中的副节点与主节点的数据保持一致.当主节点执行写 ...