10.21模拟赛 猴猴吃苹果(排序)

满分做法:

手画样例,发现输出的都是以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;    
}
原文地址:https://www.cnblogs.com/lihan123/p/11716568.html