【蓝桥杯集训·每日一题】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;

}


三、知识风暴

最近公共祖先

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


目录
相关文章
|
2月前
|
人工智能 算法 Java
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1005 数字游戏
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1005 数字游戏
65 0
|
2月前
|
Java C语言 C++
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1000 kAc给糖果你吃
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1000 kAc给糖果你吃
53 0
|
2月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-999 数的潜能
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-999 数的潜能
51 0
|
2月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-997 粘木棍
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-997 粘木棍
61 0
|
2月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1007 印章
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1007 印章
37 0
|
2月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1006 拿金币
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1006 拿金币
36 0
|
2月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1004 无聊的逗
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1004 无聊的逗
56 0
|
2月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1003 礼物
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1003 礼物
63 0
|
2月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1001 跳马
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1001 跳马
38 0
|
2月前
|
移动开发 算法 Java
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-998 娜神平衡
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-998 娜神平衡
46 0