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\n",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\n",t[i].id); } return 0; }