树的DFS
树的DFS
给定一棵 个节点的树。
节点的编号为 ,其中 号节点为根节点,每个节点的编号都大于其父节点的编号。
现在,你需要回答 个询问。
每个询问给定两个整数 。
我们希望你用 DFS(深度优先搜索)算法来遍历根节点为 的子树。
我们规定,当遍历(或回溯)到某一节点时,下一个遍历的目标应该是它的未经遍历的子节点中编号最小的那一个子节点。
例如,上图实例中:
- 如果遍历根节点为 号节点的子树,则子树内各节点的遍历顺序为 。
- 如果遍历根节点为 号节点的子树,则子树内各节点的遍历顺序为 。
- 如果遍历根节点为 号节点的子树,则子树内各节点的遍历顺序为 。
- 如果遍历根节点为 号节点的子树,则子树内各节点的遍历顺序为 。
每个询问就是让你计算采用规定的 DFS 算法来遍历根节点为 的子树时,第 个被遍历到的节点的编号。
输入格式
第一行包含两个整数 。
第二行包含 个整数 ,其中 表示第 号节点的父节点的编号。
接下来 行,每行包含两个整数 ,表示一组询问。
输出格式
共 行,每组询问输出一行一个整数表示第 个被遍历到的节点的编号。
如果第 个被遍历到的节点不存在,则输出 。
数据范围
前三个测试点满足 ,。
所有测试点满足 ,,,。
输入样例:
9 6 1 1 1 3 5 3 5 7 3 1 1 5 3 4 7 3 1 8 1 9
输出样例:
3 6 8 -1 9 4
解题思路
这题还是很简单的,不过因为周赛第一题看错题意,结果卡了40分钟,最后来不及写完这题。
题目就是问一棵树深度优先遍历的序列。然后给的一个结点编号,求以这个结点为子树的深度优先遍历序列的第个结点。
可以发现,每一棵子树在dfs序列中,一定是连续的一段。
因此,先将整棵树的dfs序列求出来,然后求以为根节点的子树的dfs序列中的第个结点,这个序列一定是后面连续的一段,如果大于这个子树的大小,则无解。
AC代码如下:
1 #include <cstdio> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 6 const int N = 2e5 + 10; 7 8 vector<int> graph[N]; 9 int order[N], h[N], cnt; // order存放dfs序列,h是每个结点在order中的下标映射 10 int sum[N]; // sum存放每个以结点为子树的大小 11 12 int dfs(int src) { 13 order[cnt] = src; 14 h[src] = cnt++; 15 sum[src] = 1; 16 17 for (auto &it : graph[src]) { 18 sum[src] += dfs(it); 19 } 20 21 return sum[src]; 22 } 23 24 int main() { 25 int n, m; 26 scanf("%d %d", &n, &m); 27 for (int i = 2; i <= n; i++) { 28 int root; 29 scanf("%d", &root); 30 graph[root].push_back(i); 31 } 32 33 dfs(1); 34 35 while (m--) { 36 int u, k; 37 scanf("%d %d", &u, &k); 38 if (k > sum[u]) printf("-1\n"); 39 else printf("%d\n", order[h[u] + k - 1]); 40 } 41 42 return 0; 43 }
参考资料
DFS序列:https://www.acwing.com/video/3723/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/15971056.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效