满分做法:
手画样例,发现输出的都是以k为根的叶子节点。于是我们按照以下步骤去操作即可:
1.先按以k为根,进行dfs处理。
2.按照节点深度及编号对节点排序,深度越大排序越靠前,深度相同时,编号小的排在前面。
3.依次处理每个节点 ,每次向上蹦,如果碰到以走过的节点或根节点就停止,记录走过的步数。
4.按照走过的步数及编号,对节点做第二次排序,得到的结果即为答案。
#include<cstring>
#include<queue>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxm=100007;
int n,k;
int pre[maxm],last[maxm],other[maxm],l;
bool vis[maxm];
int tot;
int f[maxm];
struct node
{
int id,dep;
}a[maxm];
struct srt
{
int id,ans;
}t[maxm];
bool cmp(node a,node b)
{
if(a.dep==b.dep) return a.id<b.id;
return a.dep>b.dep;
}
bool cmp1(srt a,srt b)
{
if(a.ans==b.ans) return a.id<b.id;
return a.ans>b.ans;
}
void add(int x,int y)
{
l++;
pre[l]=last[x];
last[x]=l;
other[l]=y;
}
void dfs(int x)
{
for(int p=last[x];p;p=pre[p])
{
int v=other[p];
if(vis[v]) continue;
f[v]=x;
vis[v]=1;
a[v].dep=a[x].dep+1;
a[v].id=v;
dfs(v);
}
}
int work(int x)
{
int tmp=0;
while(!vis[x])
{
vis[x]=1;
x=f[x];
tmp++;
}
return tmp;
}
int main()
{
freopen("apple.in","r",stdin);
freopen("apple.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=1;i<=n-1;i++)
{
int x;
scanf("%d",&x);
add(i,x);
add(x,i);
}
a[k].id=k;
a[k].dep=1;
vis[k]=1;
dfs(k);
sort(a,a+n,cmp);
memset(vis,0,sizeof(vis));
vis[k]=1;
printf("%d
",k);
for(int i=0;i<n;i++)
{
if(vis[a[i].id]) continue;
else
{
t[++tot].ans=work(a[i].id);
t[tot].id=a[i].id;
}
}
sort(t+1,t+tot+1,cmp1);
for(int i=1;i<=tot;i++)
{
printf("%d
",t[i].id);
}
return 0;
}