关于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 ...
随机推荐
- node.js fs、http使用
学习node核心模块http.fs;的使用 首先在server.js文件中require两个模块http.fs; let fs = require('fs')let http = require (' ...
- python 自然语言处理库https://www.nltk.org/nltk_data/
https://www.nltk.org/nltk_data/ https://github.com/hankcs/HanLP
- Spring-data-redis redis
什么是spring-data-redis spring-data-redis是spring-data模块的一部分,专门用来支持在spring管理项目对redis的操作,使用java操作redis最常用 ...
- Dubbo -- Simple Monitor
一.简介 dubbo-monitor-simple是dubbo提供的简单监控中心,可以用来显示接口暴露,注册情况,也可以看接口的调用明细,调用时间等. Simple Monitor挂掉不会影响到Con ...
- 【转】 UI自动化测试的关注点
我发现了,大家极度关心自动化测试,尤其是UI自动化测试,虽然现在作为专项测试,离开这些越来越远了,但总能遥想以前,我总能想起自己做nokia的WindowsLive的ui自动化,做web的自动化测试, ...
- PHPlaravel中从数据库中选择数据是增加时间条件及各种条件
注:附加条件后要加get函数. 1.public function getForDataTable($startTime,$endTime){ return $this->query() -&g ...
- Linux 线程】线程同步《四》
1.信号量 (1)概念 信号量和互斥锁(mutex)的区别:互斥锁只允许一个线程进入临界区,而信号量允许多个线程同时进入临界区. 不多做解释,要使用信号量同步,需要包含头文件semaphore.h. ...
- ubuntu系列-安装google浏览器
转载:http://www.linuxidc.com/Linux/2013-10/91857.htm 对于刚刚开始使用Ubuntu并想安装谷歌Chrome浏览器的新用户来说,本文所介绍的方法是最快捷的 ...
- java调用微信扫一扫
步骤: 1,获取Accesstoken(参考我之前的文章) 2,获取jsapiticket(参考我之前的文章) 3,获取签名 4JSSDK使用步骤 步骤一:绑定域名(JS接口安全域名),.否则会报in ...
- swift - 封装百度地图
1. #import <BaiduMapAPI_Base/BMKBaseComponent.h>//引入base相关所有的头文件 #import <BaiduMapAPI_Map/B ...