倍增求LCA(最近公共祖先)
题目描述:
读入一棵以1为根的树,q次询问,每次给定x和y,问x和y的最近公共祖先是哪一个节点。
树的读入格式:n-1行每行两个整数x、y,表示一条连接x和y的边,保证输入的图形成一棵树。
输入格式:
第一行两个整数为n和q,之后按题目描述读入一棵树。
再之后q行,每行两个整数x和y,表示一组询问。
输出格式:
q行,每行1个整数表示答案。
样例输入1:
10 5
2 1
2 3
2 4
5 4
3 6
7 6
8 1
1 9
1 10
9 8
3 1
7 4
6 2
10 7
样例输出1:
1
1
2
2
1
\(1\le n,q\le 10^5\)
设 \(fa_{x,i}\) 表示 \(x\) 的 \(2^i\) 级祖先,由二进制可知正确性(循环时i从大到小,详见代码),可以 \(O(n\log n)\)预处理,\(O(\log n)\)查询。
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
vector<int>g[N];
int fa[N][21],n,q,dep[N];
void dfs(int u,int deep,int fat) {
fa[u][0]=fat;
dep[u]=deep;
for(int i=0; i<g[u].size(); ++i) {
int v=g[u][i];
if(v==fat)continue;
dfs(v,deep+1,u);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=20;i>=0;--i)
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(x==y)return x;
for(int i=20;i>=0;--i)
{
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
int main() {
scanf("%d%d",&n,&q);
for(int i=1,x,y;i<n;++i)
{
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1,1,1);
for(int i=1; i<=20; ++i) {
for(int j=1; j<=n; ++j) {
fa[j][i]=fa[fa[j][i-1]][i-1];
}
}
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
return 0;
}
倍增求LCA(最近公共祖先)的更多相关文章
- 求LCA最近公共祖先的在线倍增算法模板_C++
倍增求 LCA 是在线的,而且比 ST 好写多了,理解起来比 ST 和 Tarjan 都容易,于是就自行脑补吧,代码写得容易看懂 关键理解 f[i][j] 表示 i 号节点的第 2j 个父亲,也就是往 ...
- 求LCA最近公共祖先的在线ST算法_C++
ST算法是求最近公共祖先的一种 在线 算法,基于RMQ算法,本代码用双链树存树 预处理的时间复杂度是 O(nlog2n) 查询时间是 O(1) 的 另附上离线算法 Tarjan 的链接: http ...
- 求LCA最近公共祖先的离线Tarjan算法_C++
这个Tarjan算法是求LCA的算法,不是那个强连通图的 它是 离线 算法,时间复杂度是 O(m+n),m 是询问数,n 是节点数 它的优点是比在线算法好写很多 不过有些题目是强制在线的,此类离线算法 ...
- cogs 2450. 距离 树链剖分求LCA最近公共祖先 快速求树上两点距离 详细讲解 带注释!
2450. 距离 ★★ 输入文件:distance.in 输出文件:distance.out 简单对比时间限制:1 s 内存限制:256 MB [题目描述] 在一个村子里有N个房子,一 ...
- 倍增求LCA学习笔记(洛谷 P3379 【模板】最近公共祖先(LCA))
倍增求\(LCA\) 倍增基础 从字面意思理解,倍增就是"成倍增长". 一般地,此处的增长并非线性地翻倍,而是在预处理时处理长度为\(2^n(n\in \mathbb{N}^+)\ ...
- 树上倍增求LCA(最近公共祖先)
前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...
- [算法]树上倍增求LCA
LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...
- lca最近公共祖先(模板)
洛谷上的lca模板题--传送门 学了求lca的tarjan算法(离线),在洛谷上做模板题,结果后三个点超时. 又把询问改成链式前向星,才ok. 这个博客,tarjan分析的很详细. 附代码-- #in ...
- 【倍增】洛谷P3379 倍增求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- D5 LCA 最近公共祖先
第一题: POJ 1330 Nearest Common Ancestors POJ 1330 这个题可不是以1为根节点,不看题就会一直wa呀: 加一个找根节点的措施: #include<alg ...
随机推荐
- HttpServletRequest 或 HttpServletResponse显示红色,需引用的依赖包:servlet-api.jar
解决方法:
- 「Luogu1231」教辅的组成
传送门 Luogu 解题思路 看到种匹配问题,马上想到最大流所以这就是一道SB题. 但是有一个小问题,就是每一本书都只能匹配一次,那么我们对所有书进行拆点即可,这个操作类似于这题 细节注意事项 细节有 ...
- 关于Tomcat部署项目的点点滴滴
在给客户部署环境时,我们不可能想开发一样,在编辑软件部署一下tomcat就可以正常运行.我们也应该清楚java的运行机制**“先编译,后解释”**的原则.(如下图)![图片描述][1]那么在Tomca ...
- spring源码第一章_获取源码并将源码转为eclipse工程
1.通过http://gitforwindows.org/下载github 2.通过http://services.gradle.org/distributions/下载gradle:gardle类似 ...
- java有参
一.带参数的方法 语法: 访问修饰符 方法返回值类型 方法名称 (参数列表){ // 方法体 注意:每个参数之间用","分割 二.形参和实参 形参:在方法定义时指定的参数 实 ...
- 学习Linux系统永远都不晚
作为一名机械专业毕业的学生,两年的工作经历实实在在地教会了我如何认清现实,让当初那个对机械行业无比憧憬的少年明白了自己选择的路有多艰难.由于我的父母都是工人,所以我比其他同龄人能更早地接触到工业的魅力 ...
- 从三星官方uboot开始移植
移植前的准备 下载 android_uboot_smdkv210.tar.bz2 这个文件 开始移植 本人使用的开发板是九鼎的 x210,在三星 uboot 的主 Makefile 中找到了类似的 s ...
- supervisor的介绍
1.supervisor 简介 Supervisor 是用Python开发的一个client/server服务,是Linux/Unix系统下的一个进程管理工具,不支持Windows系统.它可以很方便的 ...
- 不可不知的spark shuffle
shuffle概览 一个spark的RDD有一组固定的分区组成,每个分区有一系列的记录组成.对于由窄依赖变换(例如map和filter)返回的RDD,会延续父RDD的分区信息,以pipeline的形式 ...
- Window Server 2019 配置篇(2)- 在window server core上安装网络跟DHCP服务
上一篇我们已经建立了自己的域服务器 之后我们将安装一个window server core,也就是没有GUI只有命令行的window server,并在其上安装网络服务和DHCP 首先创建一个新的虚拟 ...