最近公共祖先(LCA)

 

祖孙询问

给定一棵包含 n 个节点的有根无向树,节点编号互不相同,但不一定是 1∼n。

有 m 个询问,每个询问给出了一对节点的编号 x 和 y,询问 x 与 y 的祖孙关系。

输入格式

输入第一行包括一个整数 表示节点个数;

接下来 n 行每行一对整数 a 和 b,表示 a和 b 之间有一条无向边。如果 b是 −1,那么 a 就是树的根;

第 n+2 行是一个整数 m 表示询问个数;

接下来 m 行,每行两个不同的正整数 x 和 y,表示一个询问。

输出格式

对于每一个询问,若 x 是 y 的祖先则输出 1,若 y 是 x 的祖先则输出 2,否则输出 0。

数据范围

1≤n,m≤4×10^4
1≤每个节点的编号≤4×10^4

输入样例:

10
234 -1
12 234
13 234
14 234
15 234
16 234
17 234
18 234
19 234
233 19
5
234 233
233 12
233 13
233 15
233 19

输出样例:

1
0
0
0
2

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=4e4+10,M=2*N;
int h[N],e[M],ne[M],idx;
int fa[N][16];
int depth[N];
int n,m;
void add(int a,int b)
{e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void bfs(int root)
{memset(depth,0x3f,sizeof depth);depth[0]=0;//哨兵depth[root]=1;//根节点深度为1queue<int>q;q.push(root);//宽搜while(q.size()){int t=q.front();q.pop();//遍历下一层for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];//此时还没有更新if(depth[j]>depth[t]+1)//depth[j]==0x3f3f3f3f{//深度加一depth[j]=depth[t]+1;q.push(j);//跳一层是j的父节点 2^0fa[j][0]=t;/*i  →  mid  →  t2^j-1  2^j-1f[i][j-1] f[i][j]mid = f[i][j-1]  t = f[i][j]则f[i][j] = f[mid][j-1] = f[f[i][j-1]][j-1]*/for(int k=1;k<=15;k++){fa[j][k]=fa[fa[j][k-1]][k-1];}/*举个例子理解超过根节点是怎么超过的因为我们没有对根节点fa[1][0]赋值,那么fa[1][0] = 0;1/ \2   3 fa[1][0] = 0;fa[2][0] = 1;fa[2][1] = fa[fa[2][0]][0] = fa[1][0] = 0;*/}}}
}
int lca(int a,int b)
{// 为方便处理 当a在b上面时 把a b 互换 if(depth[a]<depth[b]) swap(a,b);for(int k=15;k>=0;k--){//当a跳完2^k依然在b下面 我们就一直跳//二进制拼凑法 if(depth[fa[a][k]]>depth[b]){//更新跳a=fa[a][k];}}//如果跳到了b 判断一下 是否跳到了bif(a==b) return a;for(int k=15;k>=0;k--){// 假如a,b都跳出根节点,fa[a][k]==fa[b][k]==0 不符合更新条件if(fa[a][k]!=fa[a][k]){a=fa[a][k];b=fa[a][k];}}//循环结束 到达lca下一层//lca(a,b) = 再往上跳1步即可return fa[a][0];
}
int main()
{cin>>n;//初始化头节点memset(h,-1,sizeof h);int root=0;while(n--){//建图int a,b;cin>>a>>b;if(b==-1) root=a;else {add(a,b);add(b,a);}}//建depth[N] fa[N][15]bfs(root);cin>>m;while(m--){int a,b;cin>>a>>b;int num=lca(a,b);if(num==a) cout<<"1"<<endl;else if(num==b) cout<<"2"<<endl;else cout<<"0"<<endl;}return 0;
}

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

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

相关文章

leetcode每日一题2671

目录 一.题目原型 二.思路解析&#xff1a; 三.具体代码实现&#xff1a; 一.题目原型 二.思路解析&#xff1a; 其实我们可以用两个哈希表来解决这道题&#xff0c;一个哈希表hash1用来存这个数字出现了几次。另一个哈希表hash2用来存出现了几次的次数有几次&#xff0c;由于…

顶级域名类型有哪几种?顶级的域名是什么

域名有很多级别&#xff0c;如顶级域名、一级域名、二级域名、三级域名等&#xff0c;每个域名都有不同的使用级别&#xff0c;所以选择很重要适合您的那一款。 接下来新网小编就来告诉大家什么是顶级域名&#xff1f; 顶级域名有哪些类型&#xff1f; 什么是顶级域名&#xf…

手撕算法-买卖股票的最佳时机 II(买卖多次)

描述 分析 使用动态规划。dp[i][0] 代表 第i天没有股票的最大利润dp[i][1] 代表 第i天持有股票的最大利润 状态转移方程为&#xff1a;dp[i][0] max(dp[i-1][0], dp[i-1][1] prices[i]); // 前一天没有股票&#xff0c;和前一天有股票今天卖掉的最大值dp[i][1] max(dp[i-1…

vscode配置c/c++调试环境

本文记录win平台使用vscode远程连接ubuntu server服务器下&#xff0c;如何配置c/c调试环境。 过程 1. 服务器配置编译环境 这里的前置条件是vscode已经能够连接到服务器&#xff0c;第一步安装编译构建套件&#xff08;gcc、g、make、链接器等&#xff09;和调试器&#xf…

WorkPlus一站式的企业IM系统,推动企业协作与创新发展

在当代企业中&#xff0c;高效的内部通讯和协作对于企业的发展至关重要。而企业IM系统&#xff0c;作为实现内部信息交流和协作的重要工具&#xff0c;WorkPlus以其卓越的性能和功能&#xff0c;助力企业打造高效沟通与协作平台。WorkPlus提供了全面的企业IM系统解决方案。不论…

(三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练

这里写目录标题 一、colmap解算数据放入高斯1. 将稀疏重建的文件放入高斯2. 将稠密重建的文件放入高斯 二、vkitti数据放入高斯 一、colmap解算数据放入高斯 运行Colmap.bat文件之后&#xff0c;进行稀疏重建和稠密重建之后可以得到如下文件结构。 1. 将稀疏重建的文件放入高…

javaWeb奶茶商城前后台系统

一、简介 在当前数字化时代&#xff0c;电子商务已成为人们生活中不可或缺的一部分。为了满足用户对奶茶的需求&#xff0c;我设计并实现了一个基于JavaWeb的奶茶商城前后台系统。该系统涵盖了用户前台和管理员后台两大模块&#xff0c;包括登录注册、商品展示、购物车管理、订…

OpenCV学习笔记(十二)——绘制颜色直方图以及颜色空间的转换

颜色直方图 颜色直方图是计算机视觉以及图像处理中一个重要的内容&#xff0c;颜色直方图可以反映图像颜色的统计分布以及基本色调&#xff0c;通过颜色直方图可以清晰的看到各个区间的像素有多少。颜色直方图是一种全局特征&#xff0c;反映了图像或某个区域的总体颜色属性&a…

Navicat 干货 | 探索 PostgreSQL 的外部数据包装器和统计函数

PostgreSQL 因其稳定性和可扩展性而广受青睐&#xff0c;为开发人员和数据管理员提供了许多有用的函数。在这些函数中&#xff0c;file_fdw_handler、file_fdw_validator、pg_stat_statements、pg_stat_statements_info 以及 pg_stat_statements_reset 是其中的重要函数&#x…

【python 装饰器 - 重试】做一个简易重试装饰器,如果函数执行错误则会自动重新执行,可设置重试次数,对爬虫比较友好

文章日期&#xff1a;2024.03.19 使用工具&#xff1a;Python 类型&#xff1a;装饰器 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 AES解密处理&#xff08;直接解密即可&#xff09;&#xff08;crypto-js.js 标准算法&#xff09;&…

数据容器-序列-集合-Python

师从黑马程序员 序列 序列的常用操作-切片 切片&#xff1a;从一个序列中&#xff0c;取出一个子序列 语法&#xff1a;序列[起始下标:结束下标&#xff0c;步长] 注&#xff1a;此操作不会影响序列本身&#xff0c;而是会得到一个新的序列 my_list[0.1,2,3,4,5,6] result1…

谧林涓露门禁

原神武器升级材料谧林涓露和门禁好像聂。 difference(){union(){cylinder(2, 10,10, $fn365);hull(){translate([15,0,0])cylinder(1,2,2,$fn365);cylinder(1,10,10,$fn365);}}translate([15,0,-1])cylinder(4,1,1,$fn365); }