洛谷 P3379 [模板] 最近公共祖先(LCA)

news/2024/5/20 17:17:21

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

题目描述

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

输入格式

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

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

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

输出格式

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

样例 #1

样例输入 #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

提示

对于 30 % 30\% 30% 的数据, N ≤ 10 N\leq 10 N10 M ≤ 10 M\leq 10 M10

对于 70 % 70\% 70% 的数据, N ≤ 10000 N\leq 10000 N10000 M ≤ 10000 M\leq 10000 M10000

对于 100 % 100\% 100% 的数据, 1 ≤ N , M ≤ 500000 1 \leq N,M\leq 500000 1N,M500000 1 ≤ x , y , a , b ≤ N 1 \leq x, y,a ,b \leq N 1x,y,a,bN不保证 a ≠ b a \neq b a=b

原题

洛谷P3379——传送门

思路

预处理各个节点的 2 j 2^j 2j级祖先,通过倍增跳跃的方式,快速找到两个点的LCA

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;const int maxn = 5e5 + 6;vector<int> e[maxn];    // 以第i个节点为起点的有向边
int depth[maxn];        // 第i个节点的深度
int ancestor[maxn][23]; // ancestor[i][j]表示节点i的2^j级祖先
int lg[maxn];           // 预处理第i个节点的lg值void add(int x, int y) // 加有向边函数
{e[x].push_back(y);
}void dfs(int u, int fath) // dfs计算深度和祖先
{ancestor[u][0] = fath;                                    // 第1级祖先即为父亲depth[u] = depth[fath] + 1;                               // 深度为父亲深度+1for (int j = 1; j <= lg[depth[u]]; j++)                   // 计算该节点的2^j级祖先ancestor[u][j] = ancestor[ancestor[u][j - 1]][j - 1]; // 祖先的转移方程,u的2^j祖先等于u的2^(j-1)祖先的2^(j-1)祖先for (int i = 0; i < e[u].size(); i++)                     // 递归子节点{int v = e[u][i];if (fath != v)dfs(v, u);}
}int LCA(int x, int y) // 计算x和y的LCA
{if (depth[x] < depth[y]) // 让x为深度更大(或相等)的那一个swap(x, y);while (depth[x] > depth[y]) // 将x提到与y相同深度x = ancestor[x][lg[depth[x] - depth[y]] - 1];if (x == y)return x;for (int k = lg[depth[x]] - 1; k >= 0; k--) // 倍增跳跃if (ancestor[x][k] != ancestor[y][k])x = ancestor[x][k], y = ancestor[y][k];return ancestor[x][0];
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n, m, root; // 节点个数,询问个数,根节点cin >> n >> m >> root;int x, y;for (int i = 1; i <= n - 1; i++){cin >> x >> y;add(x, y);add(y, x);}for (int i = 1; i <= n; ++i)lg[i] = lg[i - 1] + (1 << lg[i - 1] == i); // 非常厉害的转移方程// 预处理节点i的2^j级祖先dfs(root, 0);// 处理询问for (int i = 1; i <= m; ++i){cin >> x >> y;cout << LCA(x, y) << '\n';}return 0;
}

http://www.mrgr.cn/p/17152723

相关文章

(8)ILA介绍

一、ILA简介二、ILA使用 在IP Catalog中选择搜索ila,选择第一个:接下来进行一些参数的配置: 配置好后生成即可: 一般情况下选择额ooc模式,可以节省资源。 在IP Sources中可以看到生成的ila ip核,比较重要的是这个.veo文件,这个相当于是ila的一个例化的模板,将该模板直接…

文件IO笔试题

文件IO 笔试题 作业:设计程序,获取当前系统时间,把时间转换为特定格式”yy年mm月dd日 星期x tt:mm:ss”,并每隔1s写入到本地磁盘中一个叫做log.txt的文本中,如果文本不存在则创建。 代码: /***************************************************************************…

预测市场?预测股票?如何让预测有更高的准确率?

我们发现在足球赛中&#xff0c;只要知道一个简单的讯息&#xff08;主队过去的获胜机率超过一半&#xff09;&#xff0c;预测力就会明显好过随便乱猜。如果再加上第二个简单的讯息&#xff08;胜负纪录较佳的队伍会略占优势&#xff09;&#xff0c;可以再进一步提升预测力。…

BGP小实验

目录拓扑图环境介绍复盘实验总结配置R3R4R1R2 拓扑图环境介绍每台路由器上都有looback0,比如R4是4.4.4.4/32,直连接口地址为10.1.34.4/24,其他路由器直连和looback口地址类似,R4上还有looback1,地址为44.44.44.44/24。 R3和R4是EBGP邻居关系,AS123内路由器是IBGP邻居关系…

Vue入门到关门之Vue3学习

一、常用API 注意:本文项目均使用脚手架为 Vite 1、setup函数 (1)介绍 如果在项目中使用配置项API,那么写起来就和vue2的写法是一样的;但是如果在项目中写的是组合式API,那么组件中所用到的:数据、方法等等,均要配置在setup中。此外,setup() 钩子也是在组件中使用组合…

线程的常见方法

线程的常见方法 休眠&#xff1a; 让当前状态不再参与cpu的竞争&#xff0c;直到休眠结束&#xff1b; 结果&#xff1a;并不是完全交替进行的&#xff0c;因为只是休眠状态&#xff0c;也会存在争抢cpu 放弃&#xff1a; 让当前状态主动放弃时间片&#xff0c;下次再去争抢…

面试集中营—Redis架构篇

一、Redis到底是多线程还是单线程 1、redis6.0版本之前的单线程&#xff0c;是指网络请求I/O与数据的读写是由一个线程完成的&#xff1b; 2、redis6.0版本升级成了多线程&#xff0c;指的是在网络请求I/O阶段应用的多线程技术&#xff1b;而键值对的读写还是由单线程完成的。所…

sso-单点登录

单点登录 项目组成 基于spring-boot-2.1.8.RELEASE,使用redis完成完成 session记录。sso-basesso-serversso-client1sso-client2 sso-baseTokenFilter: 拦截获取是否登录,并获取登录用户设置到线程变量中TokenUtil:从redis获取指定key判断是否登录,以及登录用户;写入sessi…

Vue入门到关门之Vue2高级用法

一、在vue项目中使用ref属性 ref 属性是 Vue.js 中用于获取对 DOM 元素或组件实例的引用的属性。通过在普通标签上或组件上添加 ref 属性,我们可以在 JavaScript 代码中使用 this.$refs.xxx 来访问对应的 DOM 元素或组件实例。放在普通标签上,通过 this.$refs.名字---》取到的…

Vue入门到关门之Vue3项目创建

一、vue3介绍 1、为什么要学习vue3? vue3的变化: 首先vue3完全兼容vue2,但是vue3不建议用vue2的写法;其次,vue3拥抱TypeScript,之前vue2使用的JavaScript,ts完全兼容js 最后之前学的vue2 是配置项api,而vue3是组合式api optionsAPI(旧) => compositionAPI(新), 效…

LeNet-5上手敲代码

LeNet-5 LeNet-5由Yann LeCun在1998年提出&#xff0c;旨在解决手写数字识别问题&#xff0c;被认为是卷积神经网络的开创性工作之一。该网络是第一个被广泛应用于数字图像识别的神经网络之一&#xff0c;也是深度学习领域的里程碑之一。 LeNet-5的整体架构&#xff1a; 总体…

基于Springboot的校园竞赛管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的校园竞赛管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

TB交易开拓者旗舰版自动交易的设置

本文针对TB交易开拓者旗舰版V6.0.7.0(期货程序化交易软件下载 - 交易开拓者),目前网上没有自动交易设置的完整教程&#xff0c;特写此篇。 1. 设置期货账户的自动登录和登出。点击菜单“文件/系统设置”&#xff0c;然后在“安全”tab做如下设置&#xff1a; 2 设置你的期货账…

泛域名SSL证书购买攻略!

购买泛域名证书&#xff08;也称为通配符证书&#xff09;通常涉及以下几个步骤&#xff1a; 1. 选择证书提供商&#xff1a; 首先&#xff0c;你需要选择一个信誉良好的SSL证书提供商&#xff0c;如 Sectigo、GlobalSign、DigiCert 或者JoySSL。部分云服务提供商如华为云也提供…

【前端热门框架【vue框架】】——事件处理与表单输入绑定以及学习技巧,让学习如此简单

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;程序员-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

文件IO常用的函数接口

本文归纳整理了常用的文件IO常见的函数接口及其用法,以供读者查阅 目录打开文件fopen关闭文件fclose数据读取字符读取:fgetc、getc、getchar按行读取:fgets、gets按块读取:fread写入文件字符写入:fputc、putc、putchar按行写入:fputs、puts按块写入:fwrite文件位置(光标位…

Android 高版本实现沉浸式状态栏

目前实现的android高版本沉浸式状态栏分为两类&#xff1a; 1、是纯透明状态栏&#xff1b; 2、是纯透明状态栏&#xff0c;但是状态栏字体是黑色&#xff1b; 将状态栏的代码封装到BaseActivity中更方便使用&#xff1a; BaseActivity: public abstract class BaseActivit…

uniapp开发的小程序toast被键盘遮挡提示内容无法完全显示问题解决

文章目录 问题描述问题解决参考链接&#xff1a; 问题描述 在开发抖音小程序后&#xff0c;当用户提交反馈后&#xff0c;调用了系统的toast来显示是否提交成功&#xff0c;结果被系统的键盘给盖住&#xff0c;无法显示完全。 即&#xff0c;简单来说&#xff1a;Toast会被弹…

python教程6.6-发送邮件smtplib

实现步骤: Python对SMTP⽀持有 smtplib 和 email 两个模块, email 负责构造邮件, smtplib 负责发送邮件,它对smtp协议进⾏了简单的封装。 简单代码示例:发送html格式的邮件:在html中插入图片: