当前位置: 首页 > news >正文

【蓝桥杯集训·每日一题】AcWing 3555. 二叉树

文章目录

  • 一、题目
    • 1、原题链接
    • 2、题目描述
  • 二、解题报告
    • 1、思路分析
    • 2、时间复杂度
    • 3、代码详解
  • 三、知识风暴
  • 最近公共祖先

一、题目

1、原题链接

3555. 二叉树

2、题目描述

给定一个 n 个结点(编号 1∼n)构成的二叉树,其根结点为 1 号点。

进行 m 次询问,每次询问两个结点之间的最短路径长度

树中所有边长均为 1。

输入格式

第一行包含一个整数 T,表示共有 T 组测试数据。

每组数据第一行包含两个整数 n,m。

接下来 n 行,每行包含两个整数,其中第 i 行的整数表示结点 i 的子结点编号。如果没有子结点则输出 −1。

接下来 m 行,每行包含两个整数,表示要询问的两个结点的编号。

输出格式

每组测试数据输出 m 行,代表查询的两个结点之间的最短路径长度。

数据范围

1≤T≤10,1≤n,m≤1000

输入样例

1
8 4
2 3
4 5
6 -1
-1 -1
-1 7
-1 -1
8 -1
-1 -1
1 6
4 6
4 5
8 1

输出样例

2
4
2
4

二、解题报告

1、思路分析

思路来源:y总讲解视频
y总yyds

(1)可以将题目所求的两点之间的最短路径长度转化为两点距离其公共祖先的距离和。
(2)我们可以计算出所求两点距离根结点的距离d[x1]d[x2],然后再求出其最近公共祖先距离根结点的距离d[x3],则两点之间的最短长度为d[x1]+d[x2]-2*d[x3]
(3)而上述距离可以利用深搜来求,最近公共祖先可以利用爬山法:先将深度较深的点往上爬,爬到与另一个点的深度相同后,两点一起往上爬,爬到的第一个相同的点即为最近公共祖先。
(4)模拟上述过程,求解即可。

2、时间复杂度

时间复杂度为O(n*m)

3、代码详解

#include <iostream>
#include <cstring>
using namespace std;
const int N=1010;
int l[N],r[N],p[N];   //l[],r[]存储每个结点的左右儿子,p[]存储每个结点的父结点
int dist[N];          //dist[]存储每个结点到根结点的距离
int T,n,m;
//dfs求每个点距离根结点的距离
void dfs(int u,int d){     //u代表当前点编号,d代表距离dist[u]=d;        if(l[u]!=-1) dfs(l[u],d+1);    //如果左儿子存在,继续从左儿子向下延伸if(r[u]!=-1) dfs(r[u],d+1);    //如果右儿子存在,继续从右儿子向下延伸
}
//爬山法求最近公共祖先
int getLca(int x,int y){if(dist[x]>dist[y]) swap(x,y);     //始终保持y的深度比x大while(dist[y]>dist[x]) y=p[y];     //y向上爬到与x同一深度while(y!=x) x=p[x],y=p[y];         //x,y一起向上爬,直到遇到第一个公共祖先return x;
}
int main(){cin>>T;while(T--){cin>>n>>m;memset(l,-1,sizeof l);memset(r,-1,sizeof r);for(int i=1;i<=n;i++){int lc,rc;cin>>lc>>rc;l[i]=lc,r[i]=rc;if(lc!=-1) p[lc]=i;if(rc!=-1) p[rc]=i;}dfs(1,0);while(m--){int x,y;cin>>x>>y;int lca=getLca(x,y);int ans=dist[x]+dist[y]-2*dist[lca];cout<<ans<<endl;}}return 0;
}

三、知识风暴

最近公共祖先

  • 可以利用爬山法进行求解:先将位置较低的点往上爬,爬到与另一个点高度一致,然后两个点一起向上爬,直到遇到第一个公共祖先为止(即到达的点相同)。
http://www.lryc.cn/news/36944.html

相关文章:

  • 【JavaScript运行原理之V8引擎】V8引擎解析JavaScript代码原理
  • C++11:智能指针
  • ccc-pytorch-RNN(7)
  • docker安装(linux)
  • 【数据库概论】10.1 事务及其作用
  • 通讯录(C++实现)
  • 轻松掌握C++的模板与类模板,将Tamplate广泛运用于我们的编程生活
  • pandas 数据预处理+数据概览 处理技巧整理(持续更新版)
  • mmdetectionV2.x版本 训练自己的VOC数据集
  • Shell - crontab 定时 git 拉取并执行 maven 打包
  • 408考研计算机之计算机组成与设计——知识点及其做题经验篇目3:指令的寻址方式
  • 前端包管理工具:npm,yarn、cnpm、npx、pnpm
  • 推荐系统 FM因式分解
  • Maven基础入门
  • 传输层协议 TCP UDP
  • 一点就分享系列(实践篇6——上篇)【迟到补发】Yolo-High_level系列算法开源项目融入V8 旨在研究和兼容使用【持续更新】
  • buu RSA 1 (Crypto 第一页)
  • Python 二分查找:bisect库的使用
  • 性能优化之HBase性能调优
  • 图像金字塔,原理、实现及应用
  • 08-Oracle游标管理(定义,打开、获取数据及关闭游标)
  • Python判断字符串是否包含特定子串的7种方法
  • aop实现接口访问频率限制
  • Hive---窗口函数
  • JavaSe第7次笔记
  • 什么是 Service 以及描述下它的生命周期。Service 有哪些启动方法,有 什么区别,怎样停用 Service?
  • Redis部署
  • AT32F437制作Bootloader然后实现Http OTA升级
  • Springboot项目启动初始化数据缓存
  • 深度学习必备知识——模型数据集Yolo与Voc格式文件相互转化