“树上倍增” → “树中节点 x 的第 k 个祖先”
【题目描述】
在一棵树上,除根节点外,每个节点有一个父节点。
问“节点 x 的第 k 个祖先”的编号。节点编号从 1 开始。
【输入格式】
第一行,两个整数。表示树中节点个数 n,及根节点的编号 root。
接下来 n-1 行,每行两个整数 x、y,表示节点 x 与节点 y 之间有一条边。
接下来一行,含一个整数 m。表示查询的次数。
接下来 m 行,每行两个整数 x、k,表示询问“节点 x 的第 k 个祖先是谁”?
【输出格式】
输出 m 行。每行一个整数,表示“节点 x 的第 k 个祖先”的编号。如何不存在,则输出 0。
【输入样例】
5 1
5 4
2 3
1 2
4 3
3
1 1
4 3
5 3
【输出样例】
0
1
2
【数据范围】
1≤n, m≤10^6,
1≤k≤10^9。
【算法分析】
● 暴力法求解本题的代码如下。但是由于 1≤k≤10^9,故会超时(TLE)。
● 由于本题输入为无向边,故在上述采用暴力法求解的代码中,需先通过遍历确定父子关系。下面代码实现了一个在树结构中进行深度优先搜索(DFS)的递归函数,其核心功能是建立并记录每个节点的父节点关系。在首次调用时,根节点的 fa 通常传入 0 或 -1。
在此代码中:
(1)u 表示当前正在访问的节点。
(2)核心操作 pre[u]=fa,表示将节点 u 的父节点记录在 pre 数组中,这是后续进行祖先查询(如求 LCA、k 级祖先)的基础。
(3)通过 if(j != fa) 核心判断,确保只向“子节点”方向递归,避免重复访问父节点,从而正确遍历整棵树。
● 本题输入样例对应的示意图如下所示。

依据输入样例示意图,可以清晰直观地观察输出样例的结果。
● 在本文基于链式前向星、基于邻接表的代码中,要特别注意数组 f[N][LOG+5]。也就是说,此二维数组的第二维为 LOG+5,即比 LOG 略大一点。这是基于下文代码进行设计的,防止越界。
【算法代码一:链式前向星存树】
【算法代码二:邻接表存树】
【参考文献】

浙公网安备 33010602011771号