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

 

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

CodeForces 1006E Military Problem(DFS,树的选择性遍历)_第1张图片

 

 

 

CodeForces 1006E Military Problem(DFS,树的选择性遍历)_第2张图片

 

 

 CodeForces 1006E Military Problem(DFS,树的选择性遍历)_第3张图片

 

 

 

题意:

就是给出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的点遍历的次序

 

代码如下:

 1 #include 
 2 #include <string.h>
 3 #include 
 4 #include <string>
 5 #include 
 6 #include 
 7 #include 
 8 #include 
 9 #include 
10 #include <set>
11 #include 
12 #include 
13 const int INF=0x3f3f3f3f;
14 typedef long long LL;
15 const int mod=1e9+7;
16 //const double PI=acos(-1);
17 #define Bug cout<<"---------------------"<18 const int maxm=1e6+10;
19 const int maxn=2e5+10;
20 using namespace std;
21 
22 int n,m,u,k;
23 vector<int>vt[maxn];//存边
24 int son[maxn];//son[i]表示编号为i的点自身+孩子结点的总个数 
25 int rk[maxn];//rk[i]表示遍历次序为i的点的编号 
26 int sa[maxn];//sa[i]表示编号为i的点遍历的次序 
27 int cnt;//遍历次序计数器 
28 
29 void dfs(int num)
30 {
31     ++cnt;
32     rk[cnt]=num;
33     sa[num]=cnt;
34     int sum=1;
35     for(vector<int>::iterator it=vt[num].begin();it!=vt[num].end();it++)
36     {
37         int v=*it;
38         dfs(v);
39         sum+=son[v];
40     }
41     son[num]=sum;
42 }
43 
44 int main()
45 {
46     int n,m;
47     scanf("%d %d",&n,&m);
48     for(int i=2;i<=n;i++)
49     {
50         int t;
51         scanf("%d",&t);
52         vt[t].push_back(i);
53     }
54     dfs(1);//预处理 
55     for(int i=0;i)
56     {
57         scanf("%d %d",&u,&k);
58         if(son[u]//孩子数小于k 
59             printf("-1\n");
60         else
61             printf("%d\n",rk[sa[u]+k-1]);
62     }
63     return 0;
64 }

 

 

 

 

 

 

你可能感兴趣的:(CodeForces 1006E Military Problem(DFS,树的选择性遍历))