题意是给出一个有根树,然后给出多组询问,每个询问要你求它的编号为U的结点的DFS序的第K个儿子。
分析:这道题好像之前在校赛上有一道类似的,校赛有一题是让你按顺序输出一棵树上的结点编号。这道题的一般思路就是建一棵树,在树上跑一下DFS得出结果。但是这么做比较麻烦,也容易写歪。
这题其实我们无需建树(校赛上那道题的标准做法也没有建树),直接用dfs预处理每一个结点对应的子树的数量和对应的结点个数。预处理以后,一个数组存放某一结点编号对应的dfs序号,另一个数组存放某一dfs序号对应的结点编号。然后题目给你u以后,你可以先查询到u的dfs序号,然后+k-1,再查询这个dfs序号对应的结点编号,就是答案。(其实就是以根节点为绝对参考,再给你一个相对参考和位置关系,让你查询绝对参考下的编号)
这题有一个条件,就是u的第k个儿子不存在输出“-1”,要操作这个我们再引入一个数组,数组存u有几个子树,如果子树数量比k小,就输出-1。
代码:
#include<cstdio>
#include<algorithm>
#include<vector>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 2e5+10;
queue<int>que[maxn];
int a[maxn],b[maxn],sum[maxn];////a存dfs序号,b存序号对应的结点编号
int cnt1=1;
void dfs(int k)
{
int cnt2=0;
while(que[k].empty()==false)
{
int t=que[k].front();
cnt2++;
que[k].pop();
cnt1++;
a[t]=cnt1;
b[cnt1]=t;
dfs(t);
cnt2+=sum[t];
}
sum[k]+=cnt2;
return;
}
int main()
{
memset(sum,0,sizeof(sum));
int n,q,tem,x,y;
cin>>n>>q;
for(int i=1; i<n; i++)
{
cin>>tem;
que[tem].push(i+1);
}
dfs(1);
a[1]=1;
b[1]=1;
while(q--)
{
cin>>x>>y;
if(sum[x]+1<y)
cout<<"-1"<<endl;
else cout<<b[a[x]+y-1]<<endl;
}
return 0;
}