LCA树上倍增
LCA就是最近公共祖先,比如
节点10和11的LCA就是8,9和3的LCA就是3。
我们这里讲一下用树上倍增来求LCA。
大家都可以写出暴力解法,两个节点依次一步一步往上爬,直到爬到了相同的一个节点。
二树上倍增就是对暴力的优化,改成了一次爬好几步。
具体怎么爬呢?就是两个点每次爬 2^j 步,而 j 满足的是两个点爬到的点不能相同,因为这样可能是公共祖先,但不一定是最近的。在这种条件下要使 j 尽可能的大。
举个例子,比如上图的节点7和8,当 j = 2 时,都爬到了节点 1,然而很显然这不是 LCA(7, 8),所以只能取 j = 1,7和8分别跳到3和4。然后发现3和4跳不了了,算法结束,答案就是3和4的父亲节点2。
还有一个小点,若两个点深度不同,只需让深的点往上跳到相同的深度就行。
接下来就开始写代码了。
先要预处理节点 i 跳 2^j 步跳到的点是什么。开一个数组fa[i][j],代表了节点i向上爬了2^j 步所到达的节点。那么递推式就是 fa[i][j] = fa[fa[i][j - 1]][j - 1]。
然后就直接可以求LCA了。
以洛谷的板子为例。传送门:https://www.luogu.org/problemnew/show/P3379
- #include<cstdio>
- #include<iostream>
- #include<cmath>
- #include<algorithm>
- #include<cstring>
- #include<vector>
- using namespace std;
- const int maxn = 5e5 + ;
- vector<int>v[maxn];
- int dep[maxn], fa[maxn][],vis[maxn];
- void dfs(int now) //预处理
- {
- vis[now] = ;
- for(int i = ; ( << i) <= dep[now]; ++i)
- fa[now][i] = fa[fa[now][i - ]][i - ];
- for(int i = ; i < v[now].size(); ++i)
- if(!vis[v[now][i]])
- {
- dep[v[now][i]] = dep[now] + ;
- fa[v[now][i]][] = now; //就是v[now][i]的父亲now
- dfs(v[now][i]);
- }
- }
- int lca(int x, int y) //O(logn)
- {
- if(dep[x] < dep[y]) swap(x, y);
- for(int i = ; i >= ; --i) //使x, y深度相同
- if(dep[x] - ( << i) >= dep[y]) x = fa[x][i];
- if(x == y) return x; //若两点正好重合,直接返回
- for(int i = ; i >= ; --i)
- if(fa[x][i] != fa[y][i])
- {
- x = fa[x][i]; y = fa[y][i];
- }
- return fa[x][]; //x的父亲节点就是x向上跳2^0步
- }
- int main()
- {
- int n, m, s; scanf("%d%d%d", &n, &m, &s);
- for(int i = ; i < n; ++i)
- {
- int a, b; scanf("%d%d", &a, &b);
- v[a].push_back(b); v[b].push_back(a);
- }
- dfs(s);
- while(m--)
- {
- int a, b; scanf("%d%d", &a, &b);
- printf("%d\n", lca(a, b));
- }
- return ;
- }
时间复杂度是O(nlogn)。
LCA树上倍增的更多相关文章
- Codevs 2370 小机房的树 LCA 树上倍增
题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子, ...
- HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822 Problem Description Three countries, Red, Yellow ...
- 关于树论【LCA树上倍增算法】
补了一发LCA,表示这东西表面上好像简单,但是细节真挺多. 我学的是树上倍增,倍增思想很有趣~~(爸爸的爸爸叫奶奶.偶不,爷爷)有一个跟st表非常类似的东西,f[i][j]表示j的第2^i的祖先,就是 ...
- LCA——树上倍增
首先,什么是LCA? LCA:最近公共祖先 祖先:从当前点到根节点所经过的点,包括他自己,都是这个点的祖先 A和B的公共祖先:同时是A,B两点的祖先的点 A和B的最近公共祖先:深度最大的A和B的公共祖 ...
- 洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增
倍增lca板子洛谷P3379 #include<cstdio> struct E { int to,next; }e[]; ],anc[][],log2n,deep[],n,m,s,ne; ...
- LCA树上倍增求法
1.LCA LCA就是最近公共祖先(Least common ancestor),x,y的LCA记为z=LCA(x,y),满足z是x,y的公共祖先中深度最大的那一个(即离他们最近的那一个)qwq 2. ...
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...
- 树上倍增求LCA及例题
先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...
- 两种lca的求法:树上倍增,tarjan
第一种:树上倍增 f[x,k]表示x的2^k辈祖先,即x向根结点走2^k步达到的结点. 初始条件:f[x][0]=fa[x] 递推式:f[x][k]=f[ f[x][k-1] ][k-1] 一次bfs ...
随机推荐
- bootstrap知识笔记
.nav>.active>a{ background-color:#0088cc; color:#fff; } /*! * Bootstrap v3.3.7 (http://getboot ...
- Hive基础之绪论
我本人大概是从2013年12月份开始接触Hadoop,因为公司当时要开始处理一些数据量比较大的数据,现有的通过程序去统计数据的方式在效率方面渐渐不能满足业务需求,所以便开始了Hadoop技术的探索,即 ...
- 三对角线性方程组(tridiagonal systems of equations)的求解
三对角线性方程组(tridiagonal systems of equations) 三对角线性方程组,对于熟悉数值分析的同学来说,并不陌生,它经常出现在微分方程的数值求解和三次样条函数的插值问题 ...
- C#语句 分支语句 if --- else ---
语句是指程序命令,都是按照顺序执行的.语句在程序中的执行顺序称为“控制流”或“执行流”. 根据程序对运行时所收到的输入的响应,在程序每次运行时控制流可能有所不同. 注意,语句间的标点符号必须是英文标点 ...
- 细说mysql replace into
replace语句在一般的情况下和insert差不多,但是如果表中存在primary 或者unique索引的时候,如果插入的数据和原来的primary key或者unique相同的时候,会删除原来的数 ...
- Java基础——Oracle(三)
一.Oracle内部结构 1.表空间 表空间是数据库的逻辑划分,一个表空间只属于一个数据库,每个表空间由一个或多个数据文件组成,表空间中其他的逻辑结构的数据存储在这些数据文件中,一般oracle系统安 ...
- Java-关于类
java-关于类-成员初始化问题 成员初始化出现错误“ - Syntax error on token ";", , expected” java类不允许对成员进行操作,但可 ...
- JavaScript的值传递和引用传递
译者按: 程序员应该知道递归,但是你真的知道是怎么回事么? 原文: All About Recursion, PTC, TCO and STC in JavaScript 译者: Fundebug 为 ...
- jQuery中是事件绑定方式--on、bind、live、delegate
概述:jQuery是我们最常用的js库,对于事件的绑定也是有很多种,on.one.live.bind.delegate等等,接下来我们逐一来进行讲解. 本片文章中事件所带的为版本号,例:v1.7+为1 ...
- Docker 搭建 ELK 收集并展示 tomcat 日志
架构 前端展示 --> 索引搜索 <-- 日志提取及过滤 --> 日志缓存 <-- 日志收集 Kibana --> Elastash <-- Logstash -- ...