P3379 【模板】最近公共祖先(LCA)

题目描述

如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

输入输出格式

输入格式:

第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。

接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。

接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。

输出格式:

输出包含M行,每行包含一个正整数,依次为每一个询问的结果。

输入输出样例

输入样例#1:

5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
输出样例#1:

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) -> 倍增的更多相关文章

  1. [模板] 最近公共祖先/lca

    简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...

  2. 【lhyaaa】最近公共祖先LCA——倍增!!!

    高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...

  3. luogu3379 【模板】最近公共祖先(LCA) 倍增法

    题目大意:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 整体步骤:1.使两个点深度相同:2.使两个点相同. 这两个步骤都可用倍增法进行优化.定义每个节点的Elder[i]为该节点的2^k( ...

  4. 最近公共祖先 LCA 倍增算法

          树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 ...

  5. 最近公共祖先 LCA 倍增法

    [简介] 解决LCA问题的倍增法是一种基于倍增思想的在线算法. [原理] 原理和同样是使用倍增思想的RMQ-ST 算法类似,比较简单,想清楚后很容易实现. 对于每个节点u , ancestors[u] ...

  6. 洛谷 P1439 【模板】最长公共子序列

    \[传送门啦\] 题目描述 给出\(1-n\)的两个排列\(P1\)和\(P2\),求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数\(n\), 接下来两行,每行为\(n\)个数,为 ...

  7. 洛谷 P1226 【模板】快速幂||取余运算

    题目链接 https://www.luogu.org/problemnew/show/P1226 题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 ...

  8. 洛谷P3387 【模板】缩点 题解

    背景 今天\(loj\)挂了,于是就有了闲情雅致来刷\(luogu\) 题面 洛谷P3387 [模板]缩点传送门 题意 给定一个\(n\)个点\(m\)条边有向图,每个点有一个权值,求一条路径,使路径 ...

  9. 最小生成树 & 洛谷P3366【模板】最小生成树 & 洛谷P2820 局域网

    嗯... 理解生成树的概念: 在一幅图中将所有n个点连接起来的n-1条边所形成的树. 最小生成树: 边权之和最小的生成树. 最小瓶颈生成树: 对于带权图,最大权值最小的生成树. 如何操作? 1.Pri ...

随机推荐

  1. 笔记-3:mysql数据定义

    1.定义数据库 1.1 创建数据库:创建数据库是在系统磁盘上划分一块区域用于数据的存储和管理. # 基本语法: create {database | schema} [if not exists] d ...

  2. HTML form表单中action的正确写法

    我的Java Web Application的context是myweb,即http://localhost:8080/myweb/index.jsp是欢迎页. 现在我的一个Controller的映射 ...

  3. python 比对PDF文件

    基本思路: 1.读取pdf内容,存放到不同的 list 2.比较 list 的相似度 ------------------------ 实现------------------------- 1.PD ...

  4. Ubuntu编写开机启动脚本

    1 概述 服务器一般不可能百分之百不会挂,于是一般采用主备或者分布式来达到高可用. 挂掉的机器有很多处理策略,常用的就是重新启动,但是为了保证重启之后服务器能够恢复可用状态,需要配置开机启动脚本. 2 ...

  5. Docker 启动SQLServer

    1.运行这个命令   docker run -d -e SA_PASSWORD=Docker123  -e SQLSERVER_DATABASE=qgb -e SQLSERVER_USER=sa -e ...

  6. Pattern Recognition and Machine Learning-01-Preface

    Preface Pattern recognition has its origins in engineering, whereas machine learning grew out of com ...

  7. wepy 开发小程序, 为什么设置pages路径的时候总是找不到 js 文件?

    1,路径先检查仔细了 2,别说话,重新run 3,可能是版本问题,重新搭工程

  8. Java秒杀实战 (六) 服务级高并发秒杀优化(RabbitMQ+接口优化)

    转自:https://blog.csdn.net/qq_41305266/article/details/81146716 一.思路:减少数据库访问 1.系统初始化,把商品库存数量加载到Redis 2 ...

  9. Spring7大模块

    Spring 框架是一个分层架构,由 7 个定义良好的模块组成.Spring 模块构建在核心容器之上,核心容器定义了创建.配置和管理 bean 的方式,组成 Spring 框架的每个模块(或组件)都可 ...

  10. 12.SpringMVC核心技术-请求转发和重定向

    默认情况下,跳转到指定的View,使用的是请求转发.也可以显示的进行指出 此时,需在setViewName()  指定的视图前添加 forword: , 且此时的视图不会再与视图解析器中的前缀和后缀进 ...