发现题解里面都是用 LCA 求的,这里提供一个 dfs 序的做法。
首先对整棵树进行一次 dfs ,求出每个节点的 dfs 序, $i$ 的 dfs 序记作 $id_i$ ,以 $i$ 为根的子树大小记为 $siz_i$ ,由于 dfs 序在子树中是连续的,所以 $x$ 是 $y$ 的祖先,就一定满足 $id_x \leq id_y \leq id_x + siz_x - 1$
代码很好写。
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
inline int read() {
int num = 0 ,f = 1; char c = getchar();
while (!isdigit(c)) f = c == '-' ? -1 : f ,c = getchar();
while (isdigit(c)) num = (num << 1) + (num << 3) + (c ^ 48) ,c = getchar();
return num * f;
}
const int N = 4e4 + 5 ,M = 8e4 + 5;
struct Edge {
int to ,next;
Edge (int to = 0 ,int next = 0) : to(to) ,next(next) {}
}G[M]; int head[N] ,cnt;
inline void add(int u ,int v) {
G[++cnt] = Edge(v ,head[u]); head[u] = cnt;
G[++cnt] = Edge(u ,head[v]); head[v] = cnt;
}
int siz[N] ,id[N] ,dfn;
inline void dfs(int now ,int fa) {
id[now] = ++dfn;
siz[now] = 1;
for (int i = head[now]; i ; i = G[i].next) {
int v = G[i].to;
if (v == fa) continue;
dfs(v ,now);
siz[now] += siz[v];
}
}
int rt ,n ,m;
signed main() {
n = read();
for (int i = 1; i <= n; i++) {
int u = read() ,v = read();
if (v == -1) rt = u;
else add(u ,v);
}
dfs(rt ,0);
m = read();
for (int i = 1; i <= m; i++) {
int u = read() ,v = read();
if (id[u] <= id[v] && id[v] <= id[u] + siz[u] - 1) puts("1");
else if (id[v] <= id[u] && id[u] <= id[v] + siz[v] - 1) puts("2");
else puts("0");
}
return 0;
}