[11.02] 猴猴吃苹果

题目描述

猴猴最喜欢在树上玩耍,一天猴猴又跳上了一棵树,这棵树有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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值