寻找
题目大意
给出你一棵根节点为
1
的,共有n个点的树,现在给出除了1以外其他
现在给出你一个程序
starting_time是一个容量为n的数组
current_time = 0
dfs(v):
current_time = current_time + 1
starting_time[v] = current_time
将children[v]的顺序随机排列 (每个排列的概率相同)
// children[v]v的直接儿子组成的数组
for u in children[v]:
dfs(u)
求每一个点starting_time的期望值。
输入格式
第一行一个数N,表示节点数
第二行N-1个数,第i个数表示节点i+1的父节点。
输出格式
一行N个小数,第i个数表示starting_time[i]的期望值。
样例输入
7
1 2 1 1 4 4
样例输出
1.0 4.0 5.0 3.5 4.5 5.0 5.0
数据范围
对于30%的数据,N<=1000
对于100%的数据,N<=100000
题解
假设我们已经知道了starting_time[
u
],我们简写成
设点
u
的一个儿子为
如果我们想要知道
Sv
,那我们就需要知道在遍历到点
v
之前,
我们设第
i
种选择子树(是否遍历)方案的期望值为
现在我们对第
如果不选第
j
棵子树,则有m种方案,期望和为
如果选择第
j
棵子树,则也有m种方案,期望和为
其中
Sizej
表示以
j
为根节点的子树的大小(有多少个节点)。
所以由选完1~~
化简得
F′
=
F
+
所以最后
Sv
=
Su
+
1
+∑k−1i=1Sizei2 (假设点
u
有k 个儿子)
即
Sv
=
Su
+
1
+Sizeu−Sizev−12
做一次递归并求期望值即可,一开始要预处理 Size 数组。
Code(Pascal)
var
qw:array[0..100100] of extended;
bj:array[0..100100,1..2] of longint;
fa,en,size:array[0..101000] of longint;
n,m,j,k,l,i,o,p:longint;
procedure qsort(l,r:longint);
var
i,j,m:longint;
begin
i:=l;
j:=r;
m:=bj[(l+r) div 2,1];
repeat
while bj[i,1]<m do inc(i);
while bj[j,1]>m do dec(j);
if i<=j then
begin
bj[0]:=bj[i];
bj[i]:=bj[j];
bj[j]:=bj[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;
procedure dg(o:longint);
var
xcqw:extended;
i:longint;
begin
for i:=en[o-1]+1 to en[o] do
begin
dg(bj[i,2]);
size[o]:=size[o]+size[bj[i,2]];
end;
inc(size[o]);
end;
procedure bl(o:longint);
var
i:longint;
begin
for i:=en[o-1]+1 to en[o] do
qw[bj[i,2]]:=qw[o]+(size[o]-size[bj[i,2]]-1)/2+1;
for i:=en[o-1]+1 to en[o] do
bl(bj[i,2]);
end;
begin
readln(n);
for i:=2 to n do
begin
read(fa[i]);
bj[i-1,1]:=fa[i];
bj[i-1,2]:=i;
inc(en[fa[i]]);
end;
qsort(1,n-1);
qw[1]:=1;
for i:=2 to n do
en[i]:=en[i-1]+en[i];
dg(1);
bl(1);
for i:=1 to n do
write(qw[i]:0:1,' ');
end.