给定一个 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代码:
// 最近公共祖先 #includeusing namespace std; const int N = 1010; int n, m; int l[N], r[N], p[N]; int dist[N]; 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 get_lca(int a, int b) // 优化之后就是倍增法 也可采用离线Tarjan { if (dist[a] < dist[b]) return get_lca(b, a); while (dist[a] > dist[b]) a = p[a]; while (a != b) a = p[a], b = p[b]; return a; } int main() { int T; cin >> T; while (T--) { cin >> n >> m; for (int i = 1; i <= n; i++) { int a, b; cin >> a >> b; l[i] = a, r[i] = b; if (a != -1) p[a] = i; if (b != -1) p[b] = i; } dfs(1, 0); while (m -- ) { int a, b; cin >> a >> b; int c = get_lca(a, b); cout << dist[a] + dist[b] - dist[c] * 2 << endl; } } return 0; }



