离线快速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)\)。

练习

P3379 【模板】最近公共祖先(LCA)

P3128 【USACO15DEC】 Max Flow P

离线快速LCA(最近公共祖先) Tarjan算法的更多相关文章

  1. LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现

    首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵 ...

  2. LCA 最近公共祖先 tarjan离线 总结 结合3个例题

    在网上找了一些对tarjan算法解释较好的文章 并加入了自己的理解 LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通 ...

  3. HDU 4547 CD操作 (LCA最近公共祖先Tarjan模版)

    CD操作 倍增法  https://i.cnblogs.com/EditPosts.aspx?postid=8605845 Time Limit : 10000/5000ms (Java/Other) ...

  4. LCA最近公共祖先——Tarjan模板

    LCA(Lowest Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. Tarjan是一种离线算法,时间复杂度O(n+Q),Q表示询问次数,其中 ...

  5. LCA最近公共祖先 Tarjan离线算法

    学习博客:  http://noalgo.info/476.html 讲的很清楚! 对于一颗树,dfs遍历时,先向下遍历,并且用并查集维护当前节点和父节点的集合.这样如果关于当前节点(A)的关联节点( ...

  6. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  7. LCA(最近公共祖先)算法

    参考博客:https://blog.csdn.net/my_sunshine26/article/details/72717112 首先看一下定义,来自于百度百科 LCA(Lowest Common ...

  8. LCA 近期公共祖先 小结

    LCA 近期公共祖先 小结 以poj 1330为例.对LCA的3种经常使用的算法进行介绍,分别为 1. 离线tarjan 2. 基于倍增法的LCA 3. 基于RMQ的LCA 1. 离线tarjan / ...

  9. LCA(最近公共祖先)模板

    Tarjan版本 /* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000&qu ...

  10. LCA近期公共祖先

    LCA近期公共祖先 该分析转之:http://kmplayer.iteye.com/blog/604518 1,并查集+dfs 对整个树进行深度优先遍历.并在遍历的过程中不断地把一些眼下可能查询到的而 ...

随机推荐

  1. 玄机蓝队靶场_应急响应_02:apache日志分析

    日志分析这块,感觉都是对grep.awk.sort.wc.uniq,这几个命令的使用. 一:靶场 (1)直接cd到linux日志, cd /var/log 发现apache2目录, cd ./apac ...

  2. cubeide汉化包地址

    http://mirrors.ustc.edu.cn/eclipse/technology/babel/update-site 具体步骤看洋桃物联网入门30步的视频

  3. maven 插件之 maven-shade-plugin,解决同包同名 class 共存问题的神器

    开心一刻 有一天螃蟹出门,不小心撞倒了泥鳅泥鳅很生气地说:你是不是瞎啊!螃蟹说:不是啊,我是螃蟹 概述 maven-shade-plugin 官网已经介绍的很详细了,我给大家简单翻译一下 This p ...

  4. SpringBoot 引入第三方 jar

    SpringBoot 引入第三方 jar 项目结构 -BCJS |--lib |--hsm-talos-1.0.1.jar |--src |--pom.xml step1 : 配置第三方 jar 为依 ...

  5. CSS – Flex

    前言 Flex 诞生在 Float 之后, Grid 之前, 它主要是取代 Float 来实现布局. 而它没有 cover 到的地方则由 Grid 弥补. 所以当前, 我们做布局时, 几乎不用 Flo ...

  6. DQL—查询操作

    一.查询语法 select 字段列表 from 表名列表 where 条件列表 group by 分组列表 having 分组后条件 order by 排序字段 limit 分页限定 (提供一个表来操 ...

  7. (九)Redis 哨兵机制与集群

    主从复制中,如果从库发生故障了,客户端可以继续向主库或其他从库发送请求,但是如果主库发生故障了肿么办呢?读请求,那还可以由从库继续提供服务,写请求就么得办法了.此时,哨兵机制就登场了,解决3个问题: ...

  8. Linux安装miniforge

    miniforge 安装 协议条款:bsd-3-clause 支持conda和mamba命令,两者效果一样,推荐使用mamba # Setup Miniforge wget "https:/ ...

  9. USB 逻辑分析仪分析丢包怎么分析(lecroy USB 逻辑分析仪)

    使用 LeCroy USB 逻辑分析仪分析 USB 数据传输中的丢包现象,通常涉及以下步骤: 1. 设置触发条件 在 LeCroy USB 逻辑分析仪中,设置适当的触发条件来捕获数据包丢失的场景.常见 ...

  10. opengl在编译的过程中,glad使用

    我在编译的过程中,遇到:无法找到 -lglad这个错误.最后才发现对于glad的使用不能用-lglad.因为我们通过glad的在线服务可以得到一些文件,其中glad.c文件我们是需要放在我们的项目下面 ...