题意
给出一棵树,询问两个节点的关系。
思路
LCALCALCA模板。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
const int t = 16;
int n, m, root, tot;
int f[40001][17], dfn[40001];
int head[40001], next[40001], ver[40001];
void add(int u, int v) {
ver[++tot] = v;
next[tot] = head[u];
head[u] = tot;
}
void dfs(int p, int father) {
dfn[p] = dfn[father] + 1;
f[p][0] = father;
for (int i = 1; i <= t; i++)
f[p][i] = f[f[p][i - 1]][i - 1];
for (int i = head[p]; i; i = next[i])
dfs(ver[i], p);
}
int LCA(int x, int y) {
if (dfn[x] > dfn[y]) std::swap(x, y);
if (x == y) return x;
for (int i = t; i >= 0; i--)
if (dfn[f[y][i]] >= dfn[x]) y = f[y][i];
if (x == y) return x;
for (int i = t; i >= 0; i--)
if (f[x][i] != f[y][i]) {
x = f[x][i];
y = f[y][i];
}
return f[x][0];
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int father, son;
scanf("%d %d", &son, &father);
if (father == -1) {
root = son;
continue;
}
add(father, son);
}
dfs(root, root);
scanf("%d", &m);
for (int i = 1; i <= m; i++) {
int x, y;
scanf("%d %d", &x, &y);
int z = LCA(x, y);
if (z == x) printf("1\n");
else if (z == y) printf("2\n");
else printf("0\n");
}
}