题解 猴猴吃苹果
题目描述
具体做法与心路历程
比较简单吧。题目要求我们每次找最长的链走,然后删去点权。
以 k k k为根,我们发现如下性质:
- 走的路径一定是叶子节点
- 每个点走后就没有贡献了
我们把一颗树画出来,观察即可发现,这就是长链剖分!!!
我们把链的长度赋给叶子节点,然后排序即可。
注意排序的比较!!!
C o d e \mathcal{Code} Code
/*******************************
Author:galaxy yr
LANG:C++
Created Time:2019年10月30日 星期三 14时40分57秒
*******************************/
#include<cstdio>
#include<algorithm>
using namespace std;
struct IO{
template<typename T>
IO & operator>>(T&res)
{
T q=1;char ch;
while((ch=getchar())<'0' or ch>'9')if(ch=='-')q=-q;
res=(ch^48);
while((ch=getchar())>='0' and ch<='9') res=(res<<1)+(res<<3)+(ch^48);
res*=q;
return *this;
}
}cin;
struct edge{
int to,next;
edge(int a=0,int b=0):to(a),next(b){}
};
const int maxn=5e4+10;
int n,rt,len[maxn],son[maxn],p[maxn],head[maxn],cnt,dis[maxn],stk[maxn],_top;
edge e[maxn<<1];
void add(int u,int v)
{
e[++cnt]=edge(v,head[u]);
head[u]=cnt;
}
void dfs(int now,int fa)
{
len[now]=1;
for(int i=head[now];i;i=e[i].next)
if(e[i].to!=fa)
{
dfs(e[i].to,now);
if(len[son[now]]<len[e[i].to] || (len[son[now]]==len[e[i].to] && p[e[i].to]<p[son[now]]))
son[now]=e[i].to;
}
if(!son[now])
{
stk[++_top]=now;
p[now]=now;
}
else
p[now]=p[son[now]];
len[now]=len[son[now]]+1;
}
void dfs(int now,int res,int fa)
{
if(!son[now])
{
dis[now]=res;
return;
}
else
dfs(son[now],res+1,now);
for(int i=head[now];i;i=e[i].next)
if(e[i].to!=fa && e[i].to!=son[now])
dfs(e[i].to,1,now);
}
bool cmp(int a,int b)
{
if(dis[a]==dis[b]) return a<b;
return dis[a]>dis[b];
}
int main()
{
//freopen("apple.in","r",stdin);
//freopen("apple.out","w",stdout);
cin>>n>>rt;
int u;
rt++;
for(int i=2;i<=n;i++)
{
cin>>u; u++;
add(u,i);
add(i,u);
}
dfs(rt,0);
dfs(rt,1,0);
sort(stk+1,stk+_top+1,cmp);
printf("%d\n",rt-1);
for(int i=1;i<=_top;i++)
printf("%d\n",stk[i]-1);
return 0;
}
//14:55