【原创】洛谷 LUOGU P3379 【模板】最近公共祖先(LCA) -> 倍增
P3379 【模板】最近公共祖先(LCA)
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
输入输出样例
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
4
4
1
4
4
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000
样例说明:
该树结构如下:

第一次询问:2、4的最近公共祖先,故为4。
第二次询问:3、2的最近公共祖先,故为4。
第三次询问:3、5的最近公共祖先,故为1。
第四次询问:1、2的最近公共祖先,故为4。
第五次询问:4、5的最近公共祖先,故为4。
故输出依次为4、4、1、4、4。
LCA有很多种做法,比如倍增、tarjan等。
在这里用倍增求解。
代码如下(倍增的主要思路写在程序注释里):
// LCA Least/Lowest Common Ancestor 最近公共祖先 -> 倍增
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<string>
#define MAXV 500010
#define MAXE 1000010
using namespace std;
struct tEdge{
int np;
tEdge *next;
}E[MAXE],*V[MAXV];
int tope=-;
int N,M,S;
int fa[MAXV],depth[MAXV];
int jump[][MAXV]; // jump[i][j]表示从j位置向根方向跳2^i步的节点
int getint(){
char ch='*';
while(!isdigit(ch=getchar()));
int num=ch-'';
while(isdigit(ch=getchar()))num=num*+ch-'';
return num;
}
void addedge(int u,int v){
E[++tope].np=v;
E[tope].next=V[u];
V[u]=&E[tope];
}
void dfs(int nv){
for(tEdge *ne=V[nv];ne;ne=ne->next){
if(ne->np==fa[nv])continue;
fa[ne->np]=nv;
depth[ne->np]=depth[nv]+;
dfs(ne->np);
}
}
void init_jump(){
for(int i=;i<=N;i++)
jump[][i]=fa[i];
for(int i=;i<;i++)
for(int j=;j<=N;j++)
jump[i][j]=jump[i-][jump[i-][j]];
}
int LCA(int u,int v){
if(depth[u]<depth[v])swap(u,v); // 保证u不比v浅
int ddep=depth[u]-depth[v]; // 计算深度差
for(int i=;i<;i++)
if(ddep&(<<i))
u=jump[i][u]; // 按位运算让u先跳ddep步使深度相等
if(u==v)return v; // v为u的祖先,两者LCA为v
for(int i=;i>=;i--)
if(jump[i][u]!=jump[i][v])
u=jump[i][u],v=jump[i][v]; // 保证不跳到一起
return fa[u]; // 最后就能跳到LCA的两个不同子节点
}
int main(){
N=getint(),M=getint(),S=getint();
int u,v;
for(int i=;i<N;i++){
u=getint(),v=getint();
addedge(u,v);
addedge(v,u);
}
dfs(S);
init_jump();
for(int i=;i<=M;i++){
u=getint(),v=getint();
printf("%d\n",LCA(u,v));
}
return ;
}
【原创】洛谷 LUOGU P3379 【模板】最近公共祖先(LCA) -> 倍增的更多相关文章
- [模板] 最近公共祖先/lca
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...
- 【lhyaaa】最近公共祖先LCA——倍增!!!
高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...
- luogu3379 【模板】最近公共祖先(LCA) 倍增法
题目大意:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 整体步骤:1.使两个点深度相同:2.使两个点相同. 这两个步骤都可用倍增法进行优化.定义每个节点的Elder[i]为该节点的2^k( ...
- 最近公共祖先 LCA 倍增算法
树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 ...
- 最近公共祖先 LCA 倍增法
[简介] 解决LCA问题的倍增法是一种基于倍增思想的在线算法. [原理] 原理和同样是使用倍增思想的RMQ-ST 算法类似,比较简单,想清楚后很容易实现. 对于每个节点u , ancestors[u] ...
- 洛谷 P1439 【模板】最长公共子序列
\[传送门啦\] 题目描述 给出\(1-n\)的两个排列\(P1\)和\(P2\),求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数\(n\), 接下来两行,每行为\(n\)个数,为 ...
- 洛谷 P1226 【模板】快速幂||取余运算
题目链接 https://www.luogu.org/problemnew/show/P1226 题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 ...
- 洛谷P3387 【模板】缩点 题解
背景 今天\(loj\)挂了,于是就有了闲情雅致来刷\(luogu\) 题面 洛谷P3387 [模板]缩点传送门 题意 给定一个\(n\)个点\(m\)条边有向图,每个点有一个权值,求一条路径,使路径 ...
- 最小生成树 & 洛谷P3366【模板】最小生成树 & 洛谷P2820 局域网
嗯... 理解生成树的概念: 在一幅图中将所有n个点连接起来的n-1条边所形成的树. 最小生成树: 边权之和最小的生成树. 最小瓶颈生成树: 对于带权图,最大权值最小的生成树. 如何操作? 1.Pri ...
随机推荐
- Codeforces 718A Efim and Strange Grade 程序分析
Codeforces 718A Efim and Strange Grade 程序分析 jerry的程序 using namespace std; typedef long long ll; stri ...
- php7和PHP5对比的新特性和性能优化
1 抽象语法树( AST) 1)在 PHP5中,从 php 脚本到 opcodes 的执行的过程是: Lexing:词法扫描分析,将源文件转换成 token 流: Parsing:语法分析,在 ...
- Python学习笔记:格式化输出
%d digit%s string%f float程序运用:name = input("please input your name:")age = int(input(" ...
- redis 入门教程
https://edu.aliyun.com/course/22/lesson/list?spm=5176.8252056.759075.5.Bbrpyz
- body测试onclick等鼠标事件无效果详解
DOM事件机制包括五部分: DOM事件级别 DOM事件流 DOM事件模型 事件代理 Event对象常见的方法和属性 但是有时候发现给body标签里设置onclick属性,不起作用,代码如下: 不管单击 ...
- asp.net mvc4 学习1
1 简介:微软在很早就看到了基于windows系统的web开发平台的需求,这时便开始提出自己的解决方案即微软的第一个基于web开发的平台ASP.再后来随着需求和性能的要求再2002年推出第二个解决方案 ...
- Java秒杀实战 (三)秒杀基本功能开发
转自:https://blog.csdn.net/qq_41305266/article/details/80991687 一.两次MD5 1. 用户端: PASS = MD5( 明文 + 固定 Sa ...
- Redis单机安装部署
1.下载: redis-4.0.8.tar.gz,存放至/data/tools下,解压: # wget http://download.redis.io/releases/redis-4.0.8.ta ...
- extension(类扩展)和 category(类别)
extension(类扩展) 简单来说,extension在.m文件中添加,所以其权限为private,所以只能拿到源码的类添加extension.另外extension是编译时决议,和interfa ...
- 设计模式之Template Method
1.设计模式的使用场景 模板方法模式(Template Method) 解释一下模板方法模式,就是指:一个抽象类中,有一个主方法,再定义1…n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承 ...