猴猴吃苹果

题目描述
猴猴最喜欢在树上玩耍,一天猴猴又跳上了一棵树,这棵树有N个苹果,每个苹果有一个编号,分别为0~N-1,它们之间由N-1个树枝相连,猴猴可以从树枝的一端爬到树枝的另一端,所以猴猴可以从任意一个苹果的位置出发爬到任意猴猴想去的苹果的位置。猴猴开始在编号为K的苹果的位置,并且把这个苹果吃了,之后每一天猴猴都要去吃一个苹果,但是树上那么多苹果吃哪个呢?猴猴想到自己去吃苹果时一定会把路上遇到的苹果都吃掉,于是猴猴决定去吃能让自己这天吃的苹果数量最多的那个苹果,如果有多个苹果满足条件,猴猴就会去吃这些中编号最小的苹果,那么猴猴会按照什么顺序吃苹果呢?
输入
第一行两个数N和K。(N<=50000)
第2-N行,第i+1行的数字Ai表示i和Ai之间有一根树枝相连。
输出
每行一个数字,依次表示猴猴所在的位置
样例输入 Copy
7 2
0
1
2
2
1
4
样例输出 Copy
2
0
6
3
5
提示

  1. 数据范围
    对于30%的数据:N<=100
    对于60%的数据:N<=1000
    对于100%的数据:N<=50000,0<=K<N
  2. 样例解释
    第一天最多可以吃到两个苹果,可以去0或6,去0 第二天最多吃两个,去6 第三天最多吃一个,去3 第四天最多吃一个,去5
    思路:长链刨分,找最长的链,将路上的权值加到叶子节点上,对叶子节点排序,输出.
//长链刨分
#include<bits/stdc++.h>
using namespace std;
const int N=50005;
int cnt;
int head[N],nxt[N*4],to[N*4],dis[N],len[N];
void add(int u,int v)
{
    to[++cnt]=v;
    nxt[cnt]=head[u];
    head[u]=cnt;
}
//dfs1求深度,父亲,儿子,还有长度
int fa[N],dep[N],son[N],p[N];
int _top;
int stk[N];
void dfs1(int now,int father)
{
    len[now]=1;
    for(int i=head[now];i;i=nxt[i])
        if(to[i]!=father)
    {
        dfs1(to[i],now);
        if(len[to[i]]>len[son[now]] ||(len[son[now]]==len[to[i]]&& p[to[i]]<p[son[now]]))
            son[now]=to[i];
    }
    if(!son[now])
    {
        stk[++_top]=now;
        p[now]=now;
    }
    else p[now]=p[son[now]];
    len[now]=len[son[now]]+1;
}
//dfs2 求距离
void dfs2(int now,int res,int father)
{
    if(!son[now])
    {
        dis[now]=res;
        return;
    }
    else dfs2(son[now],res+1,now);
    for(int i=head[now];i;i=nxt[i])
    {
        if(to[i]!=father && to[i]!=son[now])
        {
            dfs2(to[i],1,now);
        }
    }
}
bool cmp(int a,int b)
{
    if(dis[a]==dis[b])return a<b;
    return dis[a]>dis[b];
}
int main()
{
    int n,re;
    scanf("%d%d",&n,&re);
    for(int i=2;i<=n;i++)
    {
        int a;
        scanf("%d",&a);
        a++;
        add(a,i);
        add(i,a);
    }
    re++;
    dfs1(re,0);
    dfs2(re,1,0);
    sort(stk+1,stk+1+_top,cmp);
    printf("%d\n",re-1);
    for(int i=1;i<=_top;i++)
        printf("%d\n",stk[i]-1);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值