题意:一棵
解析:就是简单的 dfs。
容易发现每天去的点都是以
- 第一次先以
为根,求出深度,同时记录父节点,将点从大到小排序(如果相同则按编号从小到大排),这些点就是我们准备去的点; - 将排完序的点开始遍历,每个点往父节点上跳,直到根节点或被标记为止,跳的同时把路径上的点都标记,记录跳了好多次,这就是到这个点能吃的苹果数量;
- 将跳的次数从大到小排序,得到答案。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define INF 1e9
using namespace std;
const int maxn=50101;
int n,k,fa[maxn],head[maxn],cnt,vis[maxn];
struct node
{
int next;
int to;
}e[maxn<<1];
struct point
{
int dep;
int num;
}a[maxn];
struct answer
{
int ans;
int num;
}s[maxn];
int cmp(point a,point b)
{
if(a.dep==b.dep)
return a.num<b.num;
return a.dep>b.dep;
}
int cnm(answer a,answer b)
{
if(a.ans==b.ans)
return a.num<b.num;
return a.ans>b.ans;
}
void add(int from,int to)
{
e[++cnt].next=head[from];
e[cnt].to=to;
head[from]=cnt;
}
void dfs(int u)
{
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(vis[v])
continue;
fa[v]=u;
vis[v]=1;
a[v].dep=a[u].dep+1;
a[v].num=v;
dfs(v);
}
}
int solve(int u)
{
int sum=0;
while(!vis[u])
{
vis[u]=1;
u=fa[u];
sum++;
}
return sum;
}
int main()
{
freopen("apple.in","r",stdin);
freopen("apple.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=1;i<n;i++)
{
int x;
scanf("%d",&x);
add(x,i);
add(i,x);
}
a[k].dep=1;
a[k].num=k;
vis[k]=1;
dfs(k);
memset(vis,0,sizeof(vis));
sort(a,a+n,cmp);
vis[k]=1;
printf("%d\n",k);
for(int i=0;i<n;i++)
{
if(vis[a[i].num])
continue;
else
{
s[a[i].num].num=a[i].num;
s[a[i].num].ans=solve(a[i].num);
}
}
sort(s+1,s+n,cnm);
for(int i=0;i<n;i++)
if(s[i].ans)
printf("%d\n",s[i].num);
return 0;
}