Tarjan 算法是一种 离线算法,需要使用并查集记录某个结点的祖先结点。

并没有传说中的那么快。

过程

将询问都记录下来,将它们建成正向边和反向边。

在 dfs 的过程中,给走过的节点打上标记,同时维护并查集,这里利用了回溯的思想,如果 \(u\) 节点的这棵子树没搜完,那么 fa[u] = u;,搜完后,在更新并查集。

我们假设查询 \(u\) 和 \(v\) 的最近公共祖先,搜到节点 \(u\),如果另一个节点 \(v\) 已经被搜到过了,那么 \(v\) 点的并查集祖先就是 \(u\) 和 \(v\) 的最近公共祖先。

如果第一次查询 \(v\) 点时,发现 \(v\) 点已经被搜到了,说明 \(u\) 和 \(v\) 点在同一棵子树中,并且这个子树是所有包括了 \(u\) 点和 \(v\) 点的子树中 siz 最小的,这棵子树的根也是在所有符合条件的子树的根中离 \(u\) 和 \(v\) 最近的,即这棵子树的根就是 \(u\) 和 \(v\) 的最近公共祖先,而 \(v\) 的并查集祖先就是这个根节点。

代码

结构体记录询问

int cnt = 1;

struct query {
int v, lca, nxt;
} q[N << 1];

记录询问、初始化

for (int i = 1, x, y; i <= m; ++ i) {
scanf("%d%d", &x, &y);
add_query(x, y);
add_query(y, x);
}
for (int i = 1; i <= n; ++ i) {
fa[i] = i;
}

tarjan、并查集

void tarjan(int u) {
fa[u] = u;
vis[u] = 1;
for (int v : son[u]) {
if (!vis[v]) {
tarjan(v);
fa[v] = u;
}
}
int v;
for (int i = h[u]; i; i = q[i].nxt) {
if (vis[v = q[i].v]) {
q[i].lca = q[i ^ 1].lca = find(v);
}
}
}

fa[u] = u; 是为了保证在 \(u\) 这棵子树没有搜完的情况下,让它子树里的节点的并查集找祖先时找到的是它。

「学习笔记」tarjan求最近公共祖先的更多相关文章

  1. 「学习笔记」Min25筛

    「学习笔记」Min25筛 前言 周指导今天模拟赛五分钟秒第一题,十分钟说第二题是 \(\text{Min25}​\) 筛板子题,要不是第三题出题人数据范围给错了,周指导十五分钟就 \(\text{AK ...

  2. 「学习笔记」FFT 快速傅里叶变换

    目录 「学习笔记」FFT 快速傅里叶变换 啥是 FFT 呀?它可以干什么? 必备芝士 点值表示 复数 傅立叶正变换 傅里叶逆变换 FFT 的代码实现 还会有的 NTT 和三模数 NTT... 「学习笔 ...

  3. 「学习笔记」字符串基础:Hash,KMP与Trie

    「学习笔记」字符串基础:Hash,KMP与Trie 点击查看目录 目录 「学习笔记」字符串基础:Hash,KMP与Trie Hash 算法 代码 KMP 算法 前置知识:\(\text{Border} ...

  4. 「学习笔记」平衡树基础:Splay 和 Treap

    「学习笔记」平衡树基础:Splay 和 Treap 点击查看目录 目录 「学习笔记」平衡树基础:Splay 和 Treap 知识点 平衡树概述 Splay 旋转操作 Splay 操作 插入 \(x\) ...

  5. 「学习笔记」FFT 之优化——NTT

    目录 「学习笔记」FFT 之优化--NTT 前言 引入 快速数论变换--NTT 一些引申问题及解决方法 三模数 NTT 拆系数 FFT (MTT) 「学习笔记」FFT 之优化--NTT 前言 \(NT ...

  6. 「学习笔记」Treap

    「学习笔记」Treap 前言 什么是 Treap ? 二叉搜索树 (Binary Search Tree/Binary Sort Tree/BST) 基础定义 查找元素 插入元素 删除元素 查找后继 ...

  7. 「学习笔记」wqs二分/dp凸优化

    [学习笔记]wqs二分/DP凸优化 从一个经典问题谈起: 有一个长度为 \(n\) 的序列 \(a\),要求找出恰好 \(k\) 个不相交的连续子序列,使得这 \(k\) 个序列的和最大 \(1 \l ...

  8. 「学习笔记」倍增思想与lca

    目录 ST表 算法 预处理 查询 关于 log2 Code 预处理 查询 例题 P2880 P2048 lca 树上 RMQ 前置知识:欧拉序列 算法 Code 离线 Tarjan 算法 Code 倍 ...

  9. 「学习笔记」ST表

    问题引入 先让我们看一个简单的问题,有N个元素,Q次操作,每次操作需要求出一段区间内的最大/小值. 这就是著名的RMQ问题. RMQ问题的解法有很多,如线段树.单调队列(某些情况下).ST表等.这里主 ...

  10. 「学习笔记」递推 & 递归

    引入 假设我们想计算 \(f(x) = x!\).除了简单的 for 循环,我们也可以使用递归. 递归是什么意思呢?我们可以把 \(f(x)\) 用 \(f(x - 1)\) 表示,即 \(f(x) ...

随机推荐

  1. web自动化--窗口切换

    窗口切换 handles = driver.window_handles ------获取所有窗口句柄,返回的数据是一个列表类型 driver.switch_to.window(handles[-1] ...

  2. fiddler动态调试js

    背景   昨天获取到的网易云音乐站点的请求内容居然是加密的, 就需要动态的调试js找出params很secSeky未加密之前的内容. 调试方法   调试之前需要在目标浏览器上部署上fiddler的根证 ...

  3. spring boot 常见问题

    什么是 Spring Boot? 简单来说,spring boot 底层就是:spring + spring mvc + tomcat + 其他框架 starter: spring boot 依靠 s ...

  4. [复现]2021 DASCTF X BUUOJ 五月大联动-PWN

    [复现]2021 DASCTF X BUUOJ 五月大联动 由于我没ubuntu16就不复现第一个题了,直接第二个 正常的off by one from pwn import * context.os ...

  5. 给jui(dwz)的navTab换一套漂亮的图标

    上次讲了给jui(dwz)的菜单树换一套漂亮的图标,这次讲一下在点击菜单后,怎么把设置的漂亮图标带到navTab上去. 官方的navTab是这样显示的,除了默认的我的主页外,tab页上只有标题没有图标 ...

  6. 《MySQL是怎样运行的》第四章小结

  7. Docker-应用部署案例

    1.Docker部署mysql 拉取mysql镜像 # 查询mysql镜像 docker search mysql # 拉取镜像命令 docker pull centos/mysql-57-cento ...

  8. 关于Spring注解的基础详解(补充上次并不清楚的内容)

    注解,需要在.xml文件里面加这么一句话:<context:component-scan base-package=""/>(组件) Component注解 主要用于接 ...

  9. Linux & 标准C语言学习 <DAY9_1>

        2.函数传参:         1.函数中定义的变量属于该函数,出了该函数就不能再被别的函数直接使用         2.实参与形参之间是以赋值的方式进行传递数据的,并且是单项值传递     ...

  10. .NET应用系统的国际化-多语言翻译服务

    上篇文章我们介绍了 .NET应用系统的国际化-基于Roslyn抽取词条.更新代码 系统国际化改造整体设计思路如下: 提供一个工具,识别前后端代码中的中文,形成多语言词条,按语言.界面.模块统一管理多有 ...