【比赛】【树】【排序】猴猴吃苹果

 

 多画图多画图多画图!

 

发现输出的都是以k为根的叶子节点。

1.先按以k为根,进行dfs处理。

2.按照节点深度及编号对节点排序,深度越大排序越靠前,深度相同时,编号小的排在前面。

3.依次处理每个节点 ,每次向上蹦,如果碰到以走过的节点或根节点就停止,记录走过的步数。

4.按照走过的步数及编号,对节点做第二次排序,得到的结果即为答案。

 

这道题中的顺序很关键

然后查bug的时候发现,二维排序的时候要记得把关键字一条条列出来......

 

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,fr;
const int N=5e4+3;

int tot,head[N];
int ev[N<<1],enx[N<<1];
void add(int u,int v)
{
    ev[++tot]=v,enx[tot]=head[u],head[u]=tot;
    ev[++tot]=u,enx[tot]=head[v],head[v]=tot;
}

int dep[N],fa[N];
void dfs(int rt,int f)
{
    fa[rt]=f;
    dep[rt]=dep[f]+1;
    for(int i=head[rt];i;i=enx[i])
        if(ev[i]!=f)
            dfs(ev[i],rt);
}
int stp[N];
bool vis[N];
void count(int rt,int st)
{
    stp[st]++;
    vis[rt]=true;
    if(fa[rt] && !vis[fa[rt]] ) count(fa[rt],st);
}

bool cmp1(int a,int b)
{ return dep[a]!=dep[b] ?dep[a]>dep[b] :a<b ; }
bool cmp2(int a,int b)
{ return stp[a]!=stp[b] ?stp[a]>stp[b] :a<b ; }

int xl[N];
int main()
{
    scanf("%d%d",&n,&fr);
    printf("%d\n",fr++);
    
    int x;
    xl[1]=1;
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&x);
        add(x+1,i);
        xl[i]=i;
    }
    dfs(fr,0);
    sort(xl+1,xl+n+1,cmp1);
    
    for(int i=1;i<n;i++)
    {
        if(vis[xl[i]]) continue;
        count(xl[i],xl[i]);
    }
    sort(xl+1,xl+n+1,cmp2);
    for(int i=1;i<=n;i++)
        if(stp[xl[i]])
            printf("%d\n",xl[i]-1);
        else break;
    
    return 0;
}

 

posted @ 2019-10-23 10:09  心若笺诗  阅读(285)  评论(0编辑  收藏  举报