AcWing 4310. 树的DFS
原题链接
困难
作者:
134213
,
2022-03-21 18:50:36
,
所有人可见
,
阅读 270
dfs序列的一个性质: 每棵子树的dfs序一定是连续的一段区间;
通过这个性质 我们可以 求出 u是当前序列第几个点,然后他向后移动 k位 就是 当前子树的dfs序第k个遍历的点;
我们可以 设q[i] 为 第i个点是什么 p[i]为 i这个点在dfs序中是第几个点
所以答案 可以 是 q[ p[u]+k-1 ]
当然还要求出 每棵子树的大小 ,以免 k超出树的大小
那么怎么确定 每个点的下标是什么呢
其实 输入给出的是 每个i的父结点 1 1 1 3 5 3 5 7 然后依次遍历每一个子树 然后按照顺序给节点+1;
模拟一下样例
2的父结点是1 他是第一次遍历的 所以他出现的顺序就是1
3的父结点是1 2这时候已经遍历完了 所以3的出现顺序是2
然后遍历3的dfs 然后遍历5 5出现的顺序是3 .....
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int n,m;
const int N = 200050;
int p[N],q[N]; // p[i] i在dfs序列的下标 q[i]存 第i个点 是什么
vector<int> g[N];
int sz[N];
int top;
void dfs(int u)
{
q[top]=u;p[u]=top;
top++;
sz[u]=1;
for(auto v:g[u])
{
dfs(v);
sz[u]+=sz[v];
}
}
int main()
{
cin>>n>>m;
for(int i=2;i<=n;i++)
{
int t; cin>>t;
g[t].push_back(i);
}
dfs(1);
//for(int i=1;i<=n;i++)sort(g[i].begin(),g[i].end());
while (m -- )
{
int u,k; cin>>u>>k;
if(sz[u]<k)cout<<-1<<endl;
else cout<<q[p[u]+k-1]<<endl;
}
return 0;
}
有点弱 就会这么 多了
我直接一个Orz