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