关于LCA的倍增解法的笔记
emmmmm近日刚刚学习了LCA的倍增做法,写一篇BLOG来加强一下印象w
首先 何为LCA?
LCA“光辉”是印度斯坦航空公司(HAL)为满足印度空军需要研制的单座单发轻型全天候超音速战斗攻击机,主要任务是...
LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先。
怎么样,很好理解吧!
然后,关于倍增
emmmmm,可以这么理解:
……
……
……
https://blog.csdn.net/jarjingx/article/details/8180560(太烂啦有空再自己填一下这个坑吧x
怎么样,很好理解吧!
(懒癌患者是这样的orz,对不住各位观众老爷&&神犇啦
那么!
怎么把他们结合在一起就是我们要研究的问题啦。
相信大家第一次看到形似“给出一棵树和若干结点,求他们的LCA”这种问题就会想到爆搜吧(单次最坏和平均时间复杂度都是O(n))
但是显而易见,万恶机智的出题人是不会放我们这么简单的做法过哒
这时候我们就需要在原来的爆搜上加上倍增优化一下时间复杂度(优化之后是O(nlogn))
我们给这种神秘地操作叫做 树上倍增
总而言之就是
用一个二维数组fa[i][j]来表示从第i个结点向上跳 2 ^ j 个结点所在的点,那么理所当然的fa[i][0]表示的就是i点的父结点啦
int lca(int x, int y) {
if (dep[x] > dep[y]) {
swap(x, y); //交换x点和y点,让x点在y点上♂面(噫
}
for (int i = ; i >= ; i--) {
if (dep[y] - ( << i) >= dep[x]) {
y = fa[y][i]; //把y点调整到和x点一个高度
}
}
if(x == y) {
return x; //这里是特判哦,如果调整后x点和y点一样直接返回x就行啦
}
for(int i = ; i >= ; i--) {
if(fa[x][i] == fa[y][i]) {
continue; //如果他们的父亲向上跳2 ^ i个点后是同一个点的话就找到他们的LCA啦
}
else {
x = fa[x][i];
y = fa[y][i]; //要雨♂露♂均♂沾,一起向上跳喏
}
}
return fa[x][]; 返回LCAqwqqq
}
以上就是倍增LCA的核心算法啦
然而要知道的是,现在有许多万恶机智的出题人是会卡我们的倍增哒
所以我们就需要
优化优化优化!
因为涉及到图,我们就可以用一种叫派大星链式前向星的东西来优化它(如果你不知道链式前向星可以看看这个:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int Maxv = ; int fa[Maxv * ][], head[Maxv], dep[Maxv];
int cnt, n, m, s; struct edges {
int v, next;
}edge[Maxv * ]; void add(int x, int y){
edge[cnt].v = y;
edge[cnt].next = head[x];
head[x] = cnt++;
} void dfs(int u, int father){
dep[u] = dep[father] + ;
fa[u][] = father;
for (int i = ; ( << i) <= dep[u]; i++) {
fa[u][i] = fa[fa[u][i - ]][i - ];
}
for (int i = head[u]; i != -; i = edge[i].next) {
int v = edge[i].v;
if (v != father) {
dfs(v, u);
}
}
} int lca(int x, int y) {
if (dep[x] > dep[y]) {
swap(x, y);
}
for (int i = ; i >= ; i--) {
if (dep[y] - ( << i) >= dep[x]) {
y = fa[y][i];
}
}
if(x == y) {
return x;
}
for(int i = ; i >= ; i--) {
if(fa[x][i] == fa[y][i]) {
continue;
}
else {
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][];
} int main(){
int a, b;
memset(head, -, sizeof(head));
scanf("%d %d %d", &n, &m, &s);
for (int i = ; i < n; i++) {
scanf("%d %d", &a, &b);
add(a, b);
add(b, a);
}
dfs(s, );
for(int i = ; i <= m; i++) {
scanf("%d %d", &a, &b);
printf("%d\n", lca(a, b));
}
return ;
}
关于LCA的倍增解法的笔记的更多相关文章
- LCA的倍增算法
LCA,即树上两点之间的公共祖先,求这样一个公共祖先有很多种方法: 暴力向上:O(n) 每次将深度大的点往上移动,直至二者相遇 树剖:O(logn) 在O(2n)预处理重链之后,每次就将深度大的沿重链 ...
- [模板]LCA的倍增求法解析
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 【Luogu P3379】LCA问题的倍增解法
Luogu P3379 题意:对于两个节点,寻找他们的最近公共祖先. 一个显而易见的解法是对于每一个节点我们都往上遍历一遍,记录下它每一个祖先,然后再从另一个节点出发,一步一步往上走,找到以前记录过第 ...
- LCA树上倍增
LCA就是最近公共祖先,比如 节点10和11的LCA就是8,9和3的LCA就是3. 我们这里讲一下用树上倍增来求LCA. 大家都可以写出暴力解法,两个节点依次一步一步往上爬,直到爬到了相同的一个节点. ...
- 洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增
倍增lca板子洛谷P3379 #include<cstdio> struct E { int to,next; }e[]; ],anc[][],log2n,deep[],n,m,s,ne; ...
- Codevs 2370 小机房的树 LCA 树上倍增
题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子, ...
- LCA算法倍增算法(洛谷3379模板题)
倍增(爬树)算法,刚刚学习的算法.对每一个点的父节点,就记录他的2k的父亲. 题目为http://www.luogu.org/problem/show?pid=3379 第一步先记录每一个节点的深度用 ...
- HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822 Problem Description Three countries, Red, Yellow ...
- codeforces 519E A and B and Lecture Rooms(LCA,倍增)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud E. A and B and Lecture Rooms A and B are ...
随机推荐
- vim字符串替换及小技巧
vi/vim 中可以使用 :s 命令来替换字符串.以前只会使用一种格式来全文替换,今天发现该命令有很多种写法(vi 真是强大啊,还有很多需要学习),记录几种在此,方便以后查询. :s/vivian/s ...
- 2.5、CDH 搭建Hadoop在安装(设置Cloudera Manager数据库)
步骤5:设置Cloudera Manager数据库 Cloudera Manager Server包含一个可以为自己创建和配置数据库的脚本.该脚本可以: 创建Cloudera Manager Serv ...
- HLSL
[HLSL] 1.Direct3D 9 shaders can be designed using shader model 1, shader model 2 and shader model 3; ...
- macaca自动化测试以及配置环境问题
macaca 测试和环境问题 标签(空格分隔): macaca自动化配置环境问题 macaca环境变量配置 基本环境需要准备的东西: JDK的安装及环境配置:(1.8) Node.js的安装及环境配置 ...
- .sh_history文件的管理机制
来源:http://www.aixchina.net/Article/27258 字数 1056阅读 4365评论 1赞 0 内容提要: .sh_history是在ksh中用于存储用户在shell中输 ...
- MenOS
2018-2019-120189224 <庖丁解牛Iinux内核分析>第三周学习总结 MenuOS的构造 下载内核源代码编译内核 cd ~/LinuxKernel/ wget https: ...
- Selenium 定位元素原理,基本API,显示等待,隐式等待,重试机制等等
Selenium 如何定位动态元素: 测试的时候会遇到元素每次变动的情况,例如: <div id="btn-attention_2030295">...</di ...
- TOJ 3973 Maze Again && TOJ 3128 简单版贪吃蛇
TOJ3973传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=3973 时间限制(普通 ...
- php项目执行composer install时报错
报错信息: Loading composer repositories with package informationInstalling dependencies (including requi ...
- leetcode 443. String Compression
下面反向遍历,还是正向好. void left(vector<char>& v, bool p(int)) { ; ; ; while (del < max_index) { ...