Tarjan求LCA总结
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总结的更多相关文章
- 【Tarjan】洛谷P3379 Tarjan求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 倍增\ tarjan求lca
对于每个节点v,记录anc[v][k],表示从它向上走2k步后到达的节点(如果越过了根节点,那么anc[v][k]就是根节点). dfs函数对树进行的dfs,先求出anc[v][0],再利用anc[v ...
- Tarjan求LCA
LCA问题算是一类比较经典的树上的问题 做法比较多样 比如说暴力啊,倍增啊等等 今天在这里给大家讲一下tarjan算法! tarjan求LCA是一种稳定高速的算法 时间复杂度能做到预处理O(n + m ...
- 详解使用 Tarjan 求 LCA 问题(图解)
LCA问题有多种求法,例如倍增,Tarjan. 本篇博文讲解如何使用Tarjan求LCA. 如果你还不知道什么是LCA,没关系,本文会详细解释. 在本文中,因为我懒为方便理解,使用二叉树进行示范. L ...
- 倍增 Tarjan 求LCA
...
- 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 ...
- tarjan求lca的神奇
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- Tarjan求LCA(离线)
基本思想 把要求的点对保存下来,在dfs时顺带求出来. 方法 将每个已经遍历的点指向它回溯的最高节点(遍历它的子树时指向自己),每遍历到一个点就处理它存在的询问如果另一个点已经遍历,则lca就是另一个 ...
- 图论分支-倍增Tarjan求LCA
LCA,最近公共祖先,这是树上最常用的算法之一,因为它可以求距离,也可以求路径等等 LCA有两种写法,一种是倍增思想,另一种是Tarjan求法,我们可以通过一道题来看一看, 题目描述 欢乐岛上有个非常 ...
随机推荐
- hdu 1286 找新朋友 (欧拉函数)
找新朋友 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- RDMA
什么是RDMA? 来源 https://blog.csdn.net/u011459120/article/details/78469098 1. 概述 RDMA是Remote Direct Memor ...
- [洛谷P2711]小行星
题目大意:有$n$颗行星,每颗行星的位置是$(x,y,z)$.每次可以消除一个面(即$x,y$或$z$坐标相等)的行星,求消除这些行星的最少次数. 题解:最小割,对于每一颗小行星,从 x 面的出点向 ...
- Elasticsearch报错
[2018-07-12T10:32:47,642][INFO ][o.e.b.BootstrapChecks ] [VfCcJIq] bound or publishing to a non-loop ...
- POJ1797:Heavy Transportation(改造Dijkstra)
Heavy Transportation Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 52728 Accepted: ...
- AngularJs学习——实现列表内容项的增加删除
效果截图: 说明:引入bootstrap.min.css样式库和angular.min.js的静态资源库,实现列表内容的增加和删除操作. AngularJS代码: <script src=&qu ...
- C++ 智能指针的简单实现
智能指针的用处:在c++中,使用普通指针容易造成堆内存的泄露问题,即程序员会忘记释放,以及二次释放,程序发生异常时内存泄漏等问题,而使用智能指针可以更好的管理堆内存.注意,在这里智能指针是一个类而非真 ...
- 【比赛】百度之星2017 初赛Round A
第一题 题意:给定多组数据P,每次询问P进制下,有多少数字B满足条件:只要数位之和是B的倍数,该数字就是B的倍数. 题解:此题是参考10进制下3和9倍数的特殊性质. 对于10进制,ab=10*a+b= ...
- bzoj 1192 二进制
原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=1192 继续刷水题,二进制思想 //By BLADEVIL var x :longint; ...
- bzoj1053 搜索
2013-11-16 17:43 原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=1053 因为使pi(prime[i])<20亿的i不 ...