洛谷 P3379:最近公共祖先(LCA)← 倍增+链式前向星

【题目来源】
https://www.luogu.com.cn/problem/P3379

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

【输入格式】
第一行包含三个正整数 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

【说明/提示】
对于 30% 的数据,N≤10,M≤10。
对于 70% 的数据,N≤10000,M≤10000。
对于 100% 的数据,1≤N,M≤500000,1≤x,y,a,b≤N,不保证 a≠b。

【算法分析】
● 一般来讲,求 LCA 有 3 种常见方法:
倍增RMQ+欧拉序tarjan(离线)。本题代码介绍“倍增”法求LCA。

● 设
f[x][k] 表示 x 的 2^k 辈祖先,则有 f[x][k]=f[f[x][k-1]][k-1]。显然,f[x][0] 就是 x 的 2^0=1 辈祖先,即 x 的父结点。其中,k∈[1, logn],n为树的结点个数。

● 链式前向星:https://blog.csdn.net/hnjzsyjyj/article/details/139369904
val[idx]:存储编号为 idx 的边的值
e[idx]:存储编号为 idx 的结点的值
ne[idx]:存储编号为 idx 的结点指向的结点的编号
h[a]:存储头结点 a 指向的结点的编号

【算法代码】

#include <bits/stdc++.h>
using namespace std;const int N=5e5+5;
const int M=N<<1;
int h[N],e[M],ne[M],idx;
int dep[N];
int f[N][20]; //f[x][k] represents the 2^k ancestor of x
int root;
int n,m;void add(int a,int b) {e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}void dfs(int u,int fa) {f[u][0]=fa;dep[u]=dep[fa]+1;for(int i=h[u]; ~i; i=ne[i]) {int j=e[i];if(j==fa) continue;dfs(j,u);}return;
}int LCA(int x,int y) {if(dep[x]<dep[y]) swap(x,y);for(int i=20; i>=0; i--) { //log500000 < 20if(dep[f[x][i]]>=dep[y]) x=f[x][i]; //dep[x]-(1<<i) equal to dep[f[x][i]]}if(x==y) return x;for(int i=20; i>=0; i--) {if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];}return f[x][0];
}int main() {memset(h,-1,sizeof(h)); //emphasiscin>>n>>m>>root;for(int i=1; i<n; i++) {int u,v;cin>>u>>v;add(u,v);add(v,u);}dfs(root,-1);for(int j=1; (1<<j)<=n; j++) {for(int i=1; i<=n; i++) {f[i][j]=f[f[i][j-1]][j-1];}}while(m--) {int x,y;cin>>x>>y;cout<<LCA(x,y)<<endl;}return 0;
}/*
in:
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5out:
4
4
1
4
4
*/




【参考文献】
https://blog.csdn.net/qq_49705495/article/details/131969401
https://blog.csdn.net/hnjzsyjyj/article/details/139369904




 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/28355.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI 定位!GeoSpyAI上传一张图片分析具体位置 不可思议! ! !

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;常见AI大模型部署&#xff1a;点击&#xff01; &#x1f916;Ollama部署LLM专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月16日12点23分 &#x1f004;️文章质量&#xff1a;94分…

动态规划日常刷题

力扣70.爬楼梯 class Solution {public int climbStairs(int n) {return dfs(n);}//递归 //注意每次你可以爬 1 或 2 个台阶//如果最后一步是1 就先爬到n-1 把它缩小成0-n-1的范围//如果最后一步是2 就先爬到n-2 把它缩小成0-n-2的范围 private int dfs(int i){if(i < 1){r…

代码随想录算法训练营第五十九天|115.不同的子序列、 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇

代码随想录算法训练营第五十九天 115.不同的子序列 题目链接&#xff1a;115.不同的子序列 确定dp数组以及下标的含义&#xff1a;dp[i][j] &#xff1a;以下标i - 1为结尾的s&#xff0c;和以下标j - 1为结尾的t&#xff0c;s中t的个数dp[i][j]确定递推公式&#xff1a; s[…

vue3 如何给表单添加表单效验+正则表达式

校验要求 我们的表单中有密码、电话号码 &#xff0c;两项。 我们设置用密码为3到20位的非空字符 电话号码就用目前用的电话号码正则表达式&#xff0c;要求手机号码以 1 开头&#xff0c;第二位为 3 到 9 之间的数字&#xff0c;后面跟着任意 9 个数字&#xff0c;总共是 11…

Intel HDSLB 高性能四层负载均衡器 — 代码剖析和高级特性

目录 文章目录 目录前言代码剖析软件架构目录结构配置解析启动流程分析数据面 jobs 注册数据面 jobs 执行 转发流程分析收包阶段L2 处理阶段L3 处理阶段L4 处理阶段 高级特性大象流转发优化快慢路径分离转发优化报文基础转发优化 最后参考文档 前言 在前 2 篇文章中&#xff0…

超详细的描述UItralytics中的特征增强方法

目录 yolov8导航 YOLOv8(附带各种任务详细说明链接) 各个特征增强参数概述 各个参数优缺点与调整技巧 1. hsv_h (色调调整) 2. hsv_s (饱和度调整) 3. hsv_v (亮度调整) 4. degrees (图像旋转) 5. translate (图像平移) 6. scale (图像缩放) 7. shear (图像剪切) …

Qt第三方库QHotKey设置小键盘数字快捷键

一、看了一圈没有找到可以设置小键盘的情况。 这两天在研究快捷键的使用。发现qt的里的快捷键不是全局的。找了两个第三方快捷键QHotKey&#xff0c;还有一个QxtGlobalShortcut。但是这两个都不能设置小键盘的数字。 比如QKeySequenceEdit &#xff08;Ctrl1&#xff09; 这个…

【SpringBoot】SpringBoot:构建实时聊天应用

文章目录 引言项目初始化添加依赖 配置WebSocket创建WebSocket配置类创建WebSocket处理器 创建前端页面创建聊天页面 测试与部署示例&#xff1a;编写单元测试 部署扩展功能用户身份验证消息持久化群组聊天 结论 引言 随着实时通信技术的快速发展&#xff0c;聊天应用在现代We…

Luma AI如何注册:文生视频领域的新星

文章目录 Luma AI如何注册&#xff1a;文生视频领域的新星一、Luma 注册方式二、Luma 的效果三、Luma 的优势四、Luma 的功能总结 Luma AI如何注册&#xff1a;文生视频领域的新星 近年来&#xff0c;Luma AI 凭借其在文生视频领域的创新技术&#xff0c;逐渐成为行业的新星。…

MySQL基础——多表查询和事务

目录 1多表关系 2多表查询概述 3连接查询 3.1内连接 3.2左外连接 3.3右外连接 3.4自连接 4联合查询 5子查询 5.1标量子查询(子查询结果为单个值) 5.2列子查询(子查询结果为一列) 5.3行子查询(子查询结果为一行) 5.4表子查询(子查询结果为多行多列) 6事务简介和操…

vulnhub靶场-xxe打靶教程

目录 靶机导入 信息收集 发现IP 端口扫描 目录扫描 漏洞利用 靶机下载地址&#xff1a;XXE Lab: 1 ~ VulnHub 靶机导入 导入虚拟机 开启虚拟机 信息收集 发现IP arp-scan -l 发现靶机IP是192.168.202.150 端口扫描 使用nmap进行扫描 nmap -sS -A 192.168.202.150 …

EasyRecovery2024数据恢复神器#电脑必备良品

EasyRecovery数据恢复软件&#xff0c;让你的数据重见天日&#xff01; 大家好&#xff01;今天我要给大家种草一个非常实用的软件——EasyRecovery数据恢复软件&#xff01;你是不是也曾经遇到过不小心删除了重要的文件&#xff0c;或者电脑突然崩溃导致数据丢失的尴尬情况呢&…

初识PHP

一、格式 每行以分号结尾 <?phpecho hello; ?>二、echo函数和print函数 作用&#xff1a;两个函数都是输出内容到页面中&#xff0c;多用于代码调试。 <?php echo "<h1 styletext-align: center;>test</h1>"; print "<h1 stylet…

【vue3中使用$refs】

在使用uniapp官网里的uni-popup弹出层组件时&#xff0c;要将vue2转换成vue3,&#xff0c;这里遇到了一个问题&#xff1a;vue2可以通过this访问到绑定的ref&#xff0c;但是vue3没有了this,应该怎么办呢&#xff1f; 解决方法&#xff1a; !

Footer组件在home 、search 显示,在登录、注册隐藏

footer组件显示与隐藏 我们可以根据组件身上的$route获取当前路由的信息&#xff0c;通过路由路径判断Footer显示与隐藏。配置的路由的时候&#xff0c;可以给路由添加路由元信息【meta】&#xff0c;路由需要配置对象&#xff0c;它的key不能瞎写、胡写、乱写 <template&…

基于 Nginx Ingress + 云效 AppStack 实现灰度发布

作者&#xff1a;子丑 场景简介 灰度发布是降低生产部署风险&#xff0c;提升线上服务稳定性的重要手段&#xff0c;这在当前快速迭代的软件研发中尤为重要。相对于 K8s 默认的滚动部署或者简单的 Pod 分批&#xff0c;基于流量特征的灰度发布验证更精准&#xff0c;风险更低…

将qt的子程序窗口嵌入qt的主进程主窗口中(第二种方式)

上一篇文章,存在失去焦点问题,分析可能原因是直接将子进程的窗口句柄封装到QWindow对象中之后,窗口的键盘事件可能就qt自己处理,但是目前没有搞清楚怎么处理的. 下面这种方式也类似第一种方式,不同点在于处理窗口句柄的方式. 通过自定义一个QWindow的一个子类,在子类中通过wi…

TypeScript中的Symbol,确实唯一。。。

Symbol 目录 Symbol 目录自动推断symbol unique symbol区别 自动推断 let命令声明的变量&#xff0c;推断类型为 symbol。// let定义symbol推断为symbol let sym Symbol(); //symbol但是&#xff0c;const命令声明的变量&#xff0c;如果赋值为另一个 symbol 类型的变量&…

解释双向队列(Deque)的概念,Java 中的 ArrayDeque 和 LinkedList 作为 Deque 的实现,它们各自有什么优缺点?

双向队列&#xff08;Deque&#xff0c;全称为 Double Ended Queue&#xff09;是一种具有队列和栈特性的数据结构&#xff0c;允许在两端进行元素的添加和移除操作。这意味着你可以在队列的前端&#xff08;头部&#xff09;或后端&#xff08;尾部&#xff09;进行入队&#…

从 Acme.Sh V3.0 说说 ZeroSSL

熟悉明月的都知道&#xff0c;明月一直都在使用 acme.sh 作为服务器端申请、部署、续期免费 SSL 证书的主要工具&#xff0c;今天在帮一个站长申请 SSL 证书的时候发现 acme.sh v3.0 开始默认的免费 SSL 证书变更为&#xff1a;ZeroSSL 了&#xff0c;这个 ZeroSSL 其实跟明月一…