#lCAybttg040406. 1557:祖孙询问

1557:祖孙询问

题目描述

已知一棵 nn 个节点的有根树。有 mm 个询问,每个询问给出了一对节点的编号 xxyy,询问 xxyy 的祖孙关系。


输入格式

输入第一行包括一个整数 nn 表示节点个数;

接下来 nn 行每行一对整数对 aabb 表示 aabb 之间有连边。如果 bb1-1,那么 aa 就是树的根;

n+2n+2 行是一个整数 mm 表示询问个数;

接下来 mm 行,每行两个正整数 xxyy,表示一个询问。


输出格式

对于每一个询问,输出一行一个整数:

  • xxyy 的祖先则输出 11
  • yyxx 的祖先则输出 22
  • 否则输出 00

样例

输入样例 1

10
234 -1
12 234
13 234
14 234
15 234
16 234
17 234
18 234
19 234
233 19
5
234 233
233 12
233 13
233 15
233 19

输出样例 1

1
0
0
0
2

样例解释

树的结构(括号内为节点编号):

          234 (根)
    / / | | | | \ \ \
   12 13 14 15 16 17 18 19
                         \
                         233
  • 询问 (234,233)(234,233)234234233233 的祖先 → 输出 11
  • 询问 (233,12)(233,12)233233 不是 1212 的祖先,1212 也不是 233233 的祖先 → 输出 00
  • 询问 (233,13)(233,13):同理 → 输出 00
  • 询问 (233,15)(233,15):同理 → 输出 00
  • 询问 (233,19)(233,19)1919233233 的祖先 → 输出 22

数据范围

  • 1n,m4×1041 \le n, m \le 4 \times 10^4
  • 每个节点的编号不超过 4×1044 \times 10^4

时间限制:1000 ms
内存限制:524288 KB


提示

判断祖孙关系等价于判断一个节点是否在另一个节点的子树中。

在有根树中,我们可以通过 DFS 序来判断:对树进行一次 DFS,记录每个节点进入的时间戳 in[u]in[u] 和离开的时间戳 out[u]out[u]。那么节点 uu 是节点 vv 的祖先当且仅当:

$$in[u] \le in[v] \quad \text{且} \quad out[v] \le out[u]$$

因为 uu 的子树中所有节点的 DFS 序都在 [in[u],out[u]][in[u], out[u]] 区间内。

实现步骤:

  1. 读入边,确定根节点。
  2. 从根开始 DFS,记录 in[u]in[u]out[u]out[u],同时可以记录深度 dep[u]dep[u](可选)。
  3. 对于每个询问 (x,y)(x, y)
    • 如果 in[x]in[y]in[x] \le in[y]out[y]out[x]out[y] \le out[x],输出 11
    • 否则如果 in[y]in[x]in[y] \le in[x]out[x]out[y]out[x] \le out[y],输出 22
    • 否则输出 00

时间复杂度:DFS O(n)O(n),每个询问 O(1)O(1),总复杂度 O(n+m)O(n + m),完全可以通过。

注意:节点编号范围较大且不连续,可以用数组直接存储(因为不超过 4×1044\times 10^4),或者用 map 映射,但推荐直接用数组,输入时记录最大编号即可。