AcWing 1172:祖孙询问 ← DFS序

【题目来源】
https://www.acwing.com/problem/content/1174/
https://www.luogu.com.cn/problem/U283480

【题目描述】
给定一棵包含 n 个节点的有根无向树,节点编号互不相同,但不一定是 1∼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。​​​​​​​

【输入样例】
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​​​​​​​

【数据范围】
1≤n,m≤4×10^4,
1≤每个节点的编号≤4×10^4

【算法分析】
● 假设以某结点 u 为根的子树(含 u 本身)大小为 sz[u],u 在整棵树中的 DFS 序为 ts[u],则可得结点 u 的所有子树对应的 DFS 序区间为 [ts[u],ts[u]+sz[u]-1]。
进而,可得 x 是 y 的祖先的判定代码如下所示:

bool check(int x,int y) { //in_subtree
    return ts[x]<=ts[y] && ts[y]<=ts[x]+sz[x]-1;
}

● 一棵子树的 DFS 序是整棵树的 DFS 序的连续一段。借助 DFS 序,可以快速判断一个结点是否在某个子树内。

DFS序

例如,上图中以 d 为根的子树,它的 DFS 序 {3,4,5,6} 是整棵树的 DFS 序 {1,2,3,4,5,6,7,8,9} 中的连续一段。

【算法代码】

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

const int N=4e4+5;
vector<int> g[N];
int ts[N],sz[N];
int idx,root;

void dfs(int u,int fa) {
    ts[u]=++idx;
    sz[u]=1;
    for(int t:g[u]) {
        if(t==fa) continue;
        dfs(t,u);
        sz[u]+=sz[t];
    }
}

bool check(int x,int y) { //in_subtree
    return ts[x]<=ts[y] && ts[y]<=ts[x]+sz[x]-1;
}

int main() {
    int n;
    cin>>n;
    for(int i=1; i<=n; i++) {
        int u,v;
        cin>>u>>v;
        if(v==-1) root=u;
        else {
            g[u].push_back(v);
            g[v].push_back(u);
        }
    }

    dfs(root,-1);

    int q;
    cin>>q;
    while(q--) {
        int x,y;
        cin>>x>>y;
        if(check(x,y)) cout<<"1\n";
        else if(check(y,x)) cout<<"2\n";
        else cout<<"0\n";
    }

    return 0;
}

/*
in:
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

out:
1
0
0
0
2
*/



【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/139681246
https://blog.csdn.net/hnjzsyjyj/article/details/163437811
https://www.cnblogs.com/littlehb/p/16071283.html

posted @ 2026-08-04 12:29  Triwa  阅读(2)  评论(0)    收藏  举报