题目大意:
已知一棵n个节点的有根树。有m个询问。每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系。
解题思路:
D
F
S
DFS
DFS序
o
r
L
C
A
or\ LCA
or LCA
D
F
S
DFS
DFS序,记录第一次访问此节点的时间
s
t
[
x
]
st[x]
st[x],访问完的时间
e
d
[
x
]
ed[x]
ed[x]
如果
y
y
y在
x
x
x的子树内,那么必定有
s
t
[
x
]
<
s
t
[
y
]
&
&
e
d
[
y
]
<
e
d
[
x
]
st[x]<st[y]\ \&\&\ ed[y]<ed[x]
st[x]<st[y] && ed[y]<ed[x]
A c c e p t e d c o d e : Accepted\ code: Accepted code:
#include<cstdio>
using namespace std;
struct Line {
int from, to, next;
}e[80010];
int n, m, cnt, root;
int st[40010], ed[40010], last[40010];
inline void add(int x, int y) {
e[++cnt] = (Line){x, y, last[x]}; last[x] = cnt;
}
void dfs(int now, int fa) {
++cnt;
st[now] = cnt;
for (int i = last[now]; i; i = e[i].next)
if (e[i].to != fa)
dfs(e[i].to, now);
ed[now] = cnt;
}
int main() {
scanf("%d", &n);
for (int x = 0, y = 0, i = 1; i <= n; ++i) {
scanf("%d %d", &x, &y);
if (y == -1) root = x;
else add(x, y), add(y, x);
}
cnt = 0;
dfs(root, -1);
scanf("%d", &m);
for (int x = 0, y = 0, i = 1; i <= m; ++i) {
scanf("%d %d", &x, &y);
if (st[x] < st[y] && ed[y] <= ed[x]) puts("1"); else
if (st[y] < st[x] && ed[x] <= ed[y]) puts("2"); else
puts("0");
}
}