Description
H国的社会等级森严,除了国王之外,每个人均有且只有一个直接上级,当然国王没有上级。如果A是B的上级,B是C的上级,那么A就是C的上级。绝对不会出现这样的关系:A是B的上级,B也是A的上级。
最开始的时刻是0,你要做的就是用1单位的时间把一个消息告诉某一个人,让他们自行散布消息。在任意一个时间单位中,任何一个已经接到消息的人,都可以把消息告诉他的一个直接上级或者直接下属。
现在,你想知道:
1.到底需要多长时间,消息才能传遍整个H国的所有人?
2.要使消息在传递过程中消耗的时间最短,可供选择的人有那些?
Input
输入文件的第一行为一个整数N(N≤200000),表示H国人的总数,假如人按照1到n编上了号码,国王的编号是1。
第2行到第N行(共N-1行),每一行一个整数,第i行的整数表示编号为i的人直接上级的编号。
Output
输出共计两行:
第一行为一个整数,表示最后一个人接到消息的最早时间。
第二行有若干个数,表示可供选择人的编号,按照编号从小到大的顺序输出,中间用一个空格隔开。
Sample Input
输入1: 4 1 1 1 输入2: 8 1 1 3 4 4 4 3
Sample Output
输出1: 4 1 2 3 4 输出2: 5 3 4 5 6 7
Data Constraint
对于20%的数据,满足N<=3000;
对于50%的数据,满足N<=20000;
对于100%的数据,满足N<=200000;
Solution
树形dp。
设f[i]表示处理完以i为根的子树后的最小时间,rank[j]表示j的f值在所有i的儿子中从小到大排第几。
那么考虑换根dp,设g[i]表示除去i这棵子树后,(其他部分)以i的父亲为根的整棵树的答案。
那么换根时,我们将i自己的g值和所有儿子的f值一起排序后,得到rank数组,然后再用上面的式子,就可以求出换根后以i为根的答案了。最后的问题是如何求g,因为在求i的答案时,g[i]必须已经求出,所以应该从通过i求出每个儿子的g值,那么我们将所有的儿子和自己的g值排序后,考虑删掉中间的一个x后的答案,那么这个时候x以前的数的rank不变,而x后面的数的rank要-1,所以我们预处理出一个前缀max和后缀max,表示前i个(或后i个)数中f[j]+rank[j]的最小值,那么j的g值就可以从max(pre[x-1],suf[x+1]-1)转移过来。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define I int
#define ll long long
#define F(i,a,b) for(register I i=a;i<=b;++i)
#define Fd(i,a,b) for(register I i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof a)
#define N 200005
using namespace std;
I n,x,t[N<<1],nx[N<<1],l[N],suf[N],pre[N],f[N],tot,ans[N],answer,g[N];
struct SON{I x,v;}s[N];
void rd(I &x){
x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
}
void A(I x,I y){t[++tot]=y,nx[tot]=l[x],l[x]=tot;}
I cmp(SON x,SON y){return x.v>y.v;}
I cmp2(I x,I y){return x<y;}
void dg(I x,I y){
for(I k=l[x];k;k=nx[k]) if(y!=t[k]) dg(t[k],x);
tot=0;
for(I k=l[x];k;k=nx[k]) if(y!=t[k]){s[++tot]=SON{t[k],f[t[k]]};}
sort(s+1,s+1+tot,cmp);
F(i,1,tot) f[x]=max(f[x],s[i].v+i);
}
void getans(I x,I y){
tot=0;
if(x!=1) s[++tot]=SON{-1,g[x]};
for(I k=l[x];k;k=nx[k]) if(t[k]!=y) s[++tot]=SON{t[k],f[t[k]]};
sort(s+1,s+1+tot,cmp);
pre[0]=suf[tot+1]=0;
F(i,1,tot) pre[i]=max(pre[i-1],s[i].v+i);
Fd(i,tot,1) suf[i]=max(suf[i+1],s[i].v+i-1);
F(i,1,tot) if(s[i].x>0) g[s[i].x]=max(pre[i-1],suf[i+1]);
if(answer>pre[tot]){answer=pre[tot],ans[0]=0;}
if(answer==pre[tot]) ans[++ans[0]]=x;
for(I k=l[x];k;k=nx[k]) if(y!=t[k]) getans(t[k],x);
}
I main(){
freopen("news.in","r",stdin);
freopen("news.out","w",stdout);
rd(n);
F(i,2,n){rd(x);A(x,i);A(i,x);}
dg(1,0);
answer=N+1;
getans(1,0);
sort(ans+1,ans+1+ans[0],cmp2);
printf("%d\n",answer+1);
F(i,1,ans[0]) printf("%d ",ans[i]);
return 0;
}