列表

详情


NC50471. 祖孙询问

描述

已知一棵n个节点的有根树。有m个询问,每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系。

输入描述

输入第一行包括一个整数n表示节点个数;
接下来n行每行一对整数对a和b表示a和b之间有连边。如果b是-1,那么a就是树的根;
第n+2行是一个整数m表示询问个数;
接下来m行,每行两个正整数x和y,表示一个询问。

输出描述

对于每一个询问,若x是y的祖先则输出1,若y是x的祖先则输出2,否则输出0。

示例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
0
0
0
2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 43ms, 内存消耗: 7852K, 提交时间: 2023-03-23 20:09:09

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n, m, dep[40010], fa[40010][20];
vector<int> G[40010];
void dfs(int u, int f) {
    dep[u] = dep[f] + 1;
    fa[u][0] = f;
    for (int i = 1; (1 << i) < dep[u]; i++) {
        fa[u][i] = fa[fa[u][i - 1]][i - 1];
    }
    for (auto v : G[u]) {
        if (v != f) {
            dfs(v, u);
        }
    }
}
int lca(int x, int y) {
    if (dep[x] > dep[y]) {
        swap(x, y);
    }
    for (int i = 19; i >= 0; i--) {
        if (dep[x] <= dep[y] - (1 << i)) {
            y = fa[y][i];
        }
    }
    if (x == y) {
        return x;
    }
    for (int i = 19; i >= 0; i--) {
        if (fa[x][i] != fa[y][i]) {
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}
int main() {
    scanf("%d", &n);
    int root = 0;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        if (y == -1) {
            root = x;
        } else {
            G[x].push_back(y);
            G[y].push_back(x);
        }
    }
    dfs(root, 0);
    scanf("%d", &m);
    while (m--) {
        int a, b;
        scanf("%d%d", &a, &b);
        int p = lca(a, b);
        if (p == a) {
            puts("1");
        } else if (p == b) {
            puts("2");
        } else {
            puts("0");
        }
    }
    return 0;
}

C++14(g++5.4) 解法, 执行用时: 189ms, 内存消耗: 7904K, 提交时间: 2020-01-21 11:48:43

#include <bits/stdc++.h>
using namespace std;


const int MAXN = 4e4+1;
int N, M;

vector<int> G[MAXN];
int H[MAXN];
int F[MAXN][20];

void dfs(int s, int f) {
  // cout << "dfs " << s << " " << f << endl;
  F[s][0] = f, H[s] = H[f]+1;
  for (int i = 0; i < 19; i++) F[s][i+1] = F[F[s][i]][i];
  for (auto t: G[s]) if (t != f) dfs(t, s);
}
int lca(int x, int y) {
  if (H[x] < H[y]) swap(x, y);
  for (int i = 19; i >= 0; i--) if (H[F[x][i]] >= H[y]) x = F[x][i];
  if (x == y) return x;
  for (int i = 19; i >= 0; i--) if (F[x][i] != F[y][i]) x = F[x][i], y = F[y][i];
  return F[x][0];
}

int main() {
  cin >> N;
  int root = 0;
  for (int i = 0; i < N; i++) {
    int a, b; cin >> a >> b;
    if (b == -1) root = a;
    else G[b].push_back(a), G[a].push_back(b);
  }
  dfs(root, 0);
  cin >> M;
  while (M--) {
    int x, y; cin >> x >> y;
    int z = lca(x, y);
    // cout << x << " " << y << ":" << z << endl;
    if (z == x) cout << 1 << endl;
    else if (z == y) cout << 2 << endl;
    else cout << 0 << endl;
  }
}

C++ 解法, 执行用时: 183ms, 内存消耗: 6660K, 提交时间: 2022-02-06 12:07:51

#include<bits/stdc++.h>
using namespace std;
int d[40001],f[40001][16];
vector <int> g[40001];
void init(const int &x){
	d[x] = d[f[x][0]] + 1;
	int i;
	for (i = 0;i < 15;i++)
		f[x][i + 1] = f[f[x][i]][i];
	for (i = 0;i < g[x].size();i++)
		if (g[x][i] != f[x][0]){
			f[g[x][i]][0] = x;
			init(g[x][i]);
		}
}
int lca(int x,int y){
	int t = 2;
	if (d[x] < d[y]){
		swap(x,y);
		t = 1;
	}
	for (int i = 15;i >= 0;i--)
		if (d[f[x][i]] >= d[y])
			x = f[x][i];
	if (x == y)
		return t;
	return 0;
}
int main(){
	int n,m,a,b,root;
	cin>>n;
	while (n--){
		cin>>a>>b;
		if (b == -1)
			root = a;
		else{
			g[a].push_back(b);
			g[b].push_back(a);
		}
	}
	init(root);
	cin>>m;
	while (m--){
		cin>>a>>b;
		cout<<lca(a,b)<<endl;
	}
	return 0;
}

上一题