CodeForces 1006E Military Problem(DFS,树的选择性遍历)

CodeForces 1006E Military Problem(DFS,树的选择性遍历)

http://codeforces.com/contest/1006/problem/E

 

 

 

 

 

 

 

题意:

就是给出n,m,共n个点[1,n],m次询问。第二行给出n-1个数a[i],2<=i<=n;a[i]表示i的父亲节点是a[i]。

按照题目给构建一棵树,每次询问,找到从一个结点u开始DFS到第k个的节点编号是多少,这样的点不存在时输出-1。

 

思路:

如果对每个查询都DFS一次,必超时

所以必须预处理

这里用vector存边,用son[i]表示编号为i的点自身+孩子结点的总个数 ,用rk[i]表示遍历次序为i的点的编号 ,用sa[i]表示编号为i的点遍历的次序

 

代码如下:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+7;
//const double PI=acos(-1);
#define Bug cout<<"---------------------"<<endl
const int maxm=1e6+10;
const int maxn=2e5+10;
using namespace std;

int n,m,u,k;
vector<int>vt[maxn];//存边
int son[maxn];//son[i]表示编号为i的点自身+孩子结点的总个数 
int rk[maxn];//rk[i]表示遍历次序为i的点的编号 
int sa[maxn];//sa[i]表示编号为i的点遍历的次序 
int cnt;//遍历次序计数器 

void dfs(int num)
{
    ++cnt;
    rk[cnt]=num;
    sa[num]=cnt;
    int sum=1;
    for(vector<int>::iterator it=vt[num].begin();it!=vt[num].end();it++)
    {
        int v=*it;
        dfs(v);
        sum+=son[v];
    }
    son[num]=sum;
}

int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=2;i<=n;i++)
    {
        int t;
        scanf("%d",&t);
        vt[t].push_back(i);
    }
    dfs(1);//预处理 
    for(int i=0;i<m;i++)
    {
        scanf("%d %d",&u,&k);
        if(son[u]<k)//孩子数小于k 
            printf("-1\n");
        else
            printf("%d\n",rk[sa[u]+k-1]);
    }
    return 0;
}

 

 tip:如果没说是从那个点开始,入度为0的点就为根结点;

 

 -

posted @ 2019-11-06 00:35  jiamian22  阅读(211)  评论(0编辑  收藏  举报