Bootstrap

3555.数组模拟二叉树C++两结点路径

给定一个 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

#include<iostream>
#include<cstring>
using namespace std;
const int N=1010;
int l[N],r[N],dist[N],fa[N],n,m;
void dfs(int u,int d)
{
    dist[u]=d;
    if(l[u]!=-1) dfs(l[u],d+1);
    if(r[u]!=-1) dfs(r[u],d+1);
}
int zjggjd(int a,int b)
{
    if(dist[a]<dist[b]) return zjggjd(b,a);
    while(dist[a]>dist[b]) a=fa[a];
    while(a!=b) a=fa[a],b=fa[b];
    return a;
 }
int main()
{
    int T;
    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 a,b;
            cin>>a>>b;
            l[i]=a,r[i]=b;
            if(a!=-1) fa[a]=i;
            if(b!=-1) fa[b]=i;
        }
        dfs(1,0);
        while(m--)
        {
            int a,b;
            cin>>a>>b;
            int c=zjggjd(a,b); //最近公共父节点
            cout<<dist[a]+dist[b]-2*dist[c]<<endl;
        }
    }
    return 0;
}
;