给定一棵包含 n 个节点的有根无向树,节点编号互不相同,但不一定是 1∼n 。
有 m 个询问,每个询问给出了一对节点的编号 x 和 y ,询问 x 与 y 的祖孙关系。
输入格式
输入第一行包括一个整数 表示节点个数;
接下来 n 行每行一对整数 a 和 b ,表示 a 和 b 之间有一条无向边。如果 b 是 −1 ,那么 a 就是树的根;
第 n+2 行是一个整数 m 表示询问个数;
接下来 m 行,每行两个不同的正整数 x 和 y ,表示一个询问。
输出格式
对于每一个询问,若 x 是 y 的祖先则输出 1 ,若 y 是 x 的祖先则输出 2 ,否则输出 0 。
数据范围
1≤n,m≤4×104 ,
1≤每个节点的编号≤4×104
输入样例:
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
0
0
0
2
#include <bits/stdc++.h>
using namespace std;
int cnt;
const int N = 100005;
struct node
{
int to, ne;
} a[N];
int start;
int head[N];
int pre[N][25];
void add(int x, int y)
{
cnt++;
a[cnt].to = y;
a[cnt].ne = head[x];
head[x] = cnt;
}
int n, m;
int deep[N];
void dfs(int x)
{
for (int i = head[x]; i != -1; i = a[i].ne)
{
if (!deep[a[i].to])
{
deep[a[i].to] = deep[x] + 1;
//cout <<deep[a[i].to]<<endl;
pre[a[i].to][0] = x;
dfs(a[i].to);
}
}
}
int lca(int x, int y)
{
int ans = 1;
if (deep[x] > deep[y])
{
swap(x, y);
ans = 2;
}
for (int i = 20; i >= 0; i--)
{
if (deep[pre[y][i]] >= deep[x])
y = pre[y][i];
}
return x==y?ans:0;
}
int main()
{
memset(head, -1, sizeof(head));
cin >> n;
for (int i = 1; i <= n; i++)
{
int x, y;
cin >> x >> y;
if (y == -1)
{
start = x;
}
else
{
add(x, y);
add(y, x);
}
}
deep[start] = 1;
//cout <<start<<endl;
dfs(start);
for (int i = 1; i <= 20; i++)
{
for (int j = 1; j <= 40000; j++)
pre[j][i] = pre[pre[j][i - 1]][i - 1];
}
cin >> m;
for (int i = 1; i <= m; i++)
{
int x, y;
cin >> x >> y;
cout << lca(x, y) << endl;
}
return 0;
}