Codeforces Round#498(Div.3)E. Military Problem(dfs序)

原题链接

题意是给出一个有根树,然后给出多组询问,每个询问要你求它的编号为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;
}

猜你喜欢

转载自blog.csdn.net/zero___zero/article/details/81085607
今日推荐