题目描述
猴猴最喜欢在树上玩耍,一天猴猴又跳上了一棵树,这棵树有N个苹果,每个苹果有一个编号,分别为0~N-1,它们之间由N-1个树枝相连,猴猴可以从树枝的一端爬到树枝的另一端,所以猴猴可以从任意一个苹果的位置出发爬到任意猴猴想去的苹果的位置。猴猴开始在编号为K的苹果的位置,并且把这个苹果吃了,之后每一天猴猴都要去吃一个苹果,但是树上那么多苹果吃哪个呢?猴猴想到自己去吃苹果时一定会把路上遇到的苹果都吃掉,于是猴猴决定去吃能让自己这天吃的苹果数量最多的那个苹果,如果有多个苹果满足条件,猴猴就会去吃这些中编号最小的苹果,那么猴猴会按照什么顺序吃苹果呢?
题目解析
走过的点的权值清零,那么答案是唯一的,而且终点一定会是叶子节点;
那么我们设初始节点为根节点,先遍历一次树,把所有叶子节点记录下来,以及每个点的父节点,按照深度排序;
然后让每个点沿着父亲往上跳,每跳一步答案增加1,遇到根节点或者走过的节点就停止(遇到走过的点说明上面的点取过值了)
代码
#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,rt;
int ls[N],cnt;
struct point
{
int next,to;
}a[N*4];
void add(int x,int y)
{
a[++cnt].to=y;a[cnt].next=ls[x];ls[x]=cnt;
}
int f[N],dep[N],lea[N],num,sum[N];
bool vis[N];
void dfs(int now,int fa)
{
f[now]=fa;
dep[now]=dep[fa]+1;
bool flag=0;
for(int i=ls[now];i;i=a[i].next)
{
int t=a[i].to;
if(t==fa) continue;
flag=1;
dfs(t,now);
}
if(!flag) lea[++num]=now;
}
bool cmp1(int a,int b) {return dep[a]==dep[b]?a<b:dep[a]>dep[b];}
bool cmp2(int a,int b) {return sum[a]==sum[b]?a<b:sum[a]>sum[b];}
int main()
{
scanf("%d%d",&n,&rt);
for(int x,i=1;i<n;++i)
{
scanf("%d",&x);
add(x,i);add(i,x);
}
dfs(rt,rt);
sort(lea+1,lea+num+1,cmp1);
vis[rt]=1;
for(int i=1;i<=num;++i)
{
int now=lea[i];
while(!vis[now])
{
++sum[lea[i]];
vis[now]=1;
now=f[now];
}
}
sort(lea+1,lea+num+1,cmp2);
printf("%d\n",rt);
for(int i=1;i<=num;++i) printf("%d\n",lea[i]);
return 0;
}