Tarjan算法
向上标记法:
从x向上走到根节点,并标记所有经过的点
从y向上走到根节点,当第一次遇到已标记的节点时,就找到了LCA(x, y)
对于每个询问,向上标记法的时间复杂度最坏为O(n)

在深度遍历的任意时刻,我们将树中的节点分成三类:
1.我们已经访问了,但是我们还没有回溯的节点标记为1
2.我们访问过并且已经回溯到的,标记为2
3.没有访问过的节点
对于正在访问的节点x,他的父节点是标记为1的。若y是已经访问并且回溯的节点,则LCA(x, y)就是由y向上走,遇到的第一个标记为1的节点。
我们很容易想到可以使用并查集优化。
当一个节点标记为2时,我们把它合并到他父亲所在的集合(此时他的父亲一定标记为1且单独构成一个集合)
这就相当于每个完成回溯的几点都有一个指向它的父节点的指针,只需查询y所在集合的代表元素(并查集的get操作),就等价于从y向上一直走到一个开始递归但未回溯的节点,即LCA(x, y)
其实整个过程,自己在演草纸上画一遍就好了(建议换一篇博客看看)

 #include<bits/stdc++.h>
using namespace std;
const int maxn = ;
struct shiki {
int y, net;
}e[maxn << ];
struct enkidu {
int self, id, nex;
}ask[maxn << ];
int n, m, s;
int lin[maxn], len = ;
int both[maxn], tot = ;
int fa[maxn], lca[maxn];
int vis[maxn]; inline int read() {
int x = , y = ;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') y = -;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << ) + (x << ) + ch - '';
ch = getchar();
}
return x * y;
} inline void insert(int xx, int yy) {
e[++len].y = yy;
e[len].net = lin[xx];
lin[xx] = len;
} inline void add(int xx, int yy, int i) {
ask[++tot].self = yy;
ask[tot].id = i;
ask[tot].nex = both[xx];
both[xx] = tot;
} int getfather(int x) {
if(x == fa[x]) return x;
return fa[x] = getfather(fa[x]);
} void LCA_tarjan(int x) {
vis[x] = ;
for(int i = lin[x]; i; i = e[i].net) {
int to = e[i].y;
if(vis[to]) continue;
LCA_tarjan(to);
fa[to] = x;
}
for(int i = both[x]; i; i = ask[i].nex) {
int to = ask[i].self;
if(vis[to] == )
lca[ask[i].id] = getfather(to);
}
vis[x] = ;
} int main() {
memset(vis, , sizeof(vis));
n = read(), m = read(), s = read();
for(int i = ; i < n; ++i) {
int x, y;
x = read(), y = read();
insert(x, y);
insert(y, x);
}
for(int i = ; i <= n; ++i) fa[i] = i;
for(int i = ; i <= m; ++i) {
int x, y;
x = read(), y = read();
add(x, y, i);
add(y, x, i);
}
LCA_tarjan(s);
for(int i = ; i <= m; ++i)
cout << lca[i] << '\n';
return ;
}

关于板子,它救活了

Tarjan求LCA总结的更多相关文章

  1. 【Tarjan】洛谷P3379 Tarjan求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  2. 倍增\ tarjan求lca

    对于每个节点v,记录anc[v][k],表示从它向上走2k步后到达的节点(如果越过了根节点,那么anc[v][k]就是根节点). dfs函数对树进行的dfs,先求出anc[v][0],再利用anc[v ...

  3. Tarjan求LCA

    LCA问题算是一类比较经典的树上的问题 做法比较多样 比如说暴力啊,倍增啊等等 今天在这里给大家讲一下tarjan算法! tarjan求LCA是一种稳定高速的算法 时间复杂度能做到预处理O(n + m ...

  4. 详解使用 Tarjan 求 LCA 问题(图解)

    LCA问题有多种求法,例如倍增,Tarjan. 本篇博文讲解如何使用Tarjan求LCA. 如果你还不知道什么是LCA,没关系,本文会详细解释. 在本文中,因为我懒为方便理解,使用二叉树进行示范. L ...

  5. 倍增 Tarjan 求LCA

                                                                                                         ...

  6. SPOJ 3978 Distance Query(tarjan求LCA)

    The traffic network in a country consists of N cities (labeled with integers from 1 to N) and N-1 ro ...

  7. tarjan求lca的神奇

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  8. Tarjan求LCA(离线)

    基本思想 把要求的点对保存下来,在dfs时顺带求出来. 方法 将每个已经遍历的点指向它回溯的最高节点(遍历它的子树时指向自己),每遍历到一个点就处理它存在的询问如果另一个点已经遍历,则lca就是另一个 ...

  9. 图论分支-倍增Tarjan求LCA

    LCA,最近公共祖先,这是树上最常用的算法之一,因为它可以求距离,也可以求路径等等 LCA有两种写法,一种是倍增思想,另一种是Tarjan求法,我们可以通过一道题来看一看, 题目描述 欢乐岛上有个非常 ...

随机推荐

  1. 算法学习——kruskal重构树

    kruskal重构树是一个比较冷门的数据结构. 其实可以看做一种最小生成树的表现形式. 在普通的kruskal中,如果一条边连接了在2个不同集合中的点的话,我们将合并这2个点所在集合. 而在krusk ...

  2. JUnit4.11 理论机制 @Theory 完整解读

    最近在研究JUnit4,大部分基础技术都是通过百度和JUnit的官方wiki学习的,目前最新的发布版本是4.11,结合代码实践,发现官方wiki的内容或多或少没有更新,Theory理论机制章节情况尤为 ...

  3. CodeIgniter自带的数据库类使用介绍

    在 CodeIgniter 中,使用数据库是非常频繁的事情.你可以使用框架自带的数据库类,就能便捷地进行数据库操作. 初始化数据库类 依据你的数据库配置载入并初始化数据库类: view source ...

  4. CSS中的块级元素、内联元素(行内元素)

    Block element 块级元素    顾名思义就是以块显示的元素,高度宽度都是可以设置的.比如我们常用 的<div>.<p>.<ul>默认状态下都是属于块级元 ...

  5. Spring学习-- Bean 的作用域

    Bean 的作用域: 在 Spring 中 , 可以在 <bean> 元素的 scope 属性里设置 bean 的作用域. 默认情况下 , Spring 只为每个在 IOC 容器里声明的 ...

  6. HDFS的xshell及dfsadmin命令

    一. DFS:distributied file system 是一种允许文件通过网络在多台主机上风向的文件系统,可让多机器上的多用户分享文件和存储空间 二.HDFS的shell **切记后面加的 / ...

  7. BZOJ 4206: 最大团

    4206: 最大团 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 91  Solved: 36[Submit][Status][Discuss] De ...

  8. MINA 网络黏包处理代码

    本文完整代码,可以浏览: https://github.com/hjj2017/xgame-code_server/blob/master/game_server/src/com/game/gameS ...

  9. SpringMvc基础知识(一)

    目录: springmvc框架原理(掌握) 前端控制器.处理器映射器.处理器适配器.视图解析器 springmvc入门程序 目的:对前端控制器.处理器映射器.处理器适配器.视图解析器学习 非注解的处理 ...

  10. The Clean Architecture--一篇很不错的关于架构的文章

    翻译水平有限,见谅! Uncle Bob 13 Aug 2012 Architecture Craftsmanship Over the last several years we’ve seen a ...