题意:n 个节点的树,初始位置为 1 号节点,初始时间为 1。
每次随机地走向任何一个没有走过的子树并且令时间 +1
求问走到每一个点时的时间的期望值
思路:比较少见的一道自顶向下的树形DP
dp[i]表示走到i点的期望时间
对于U,考虑它走到儿子V需要时间1,在此之前可能要由1走到U,还要走过若干U的其它子树
对于每一棵子树它对答案的贡献就是size,因为要走完所有的点才能出来
任意子树在V前走的概率是0.5,所以计算它对dp[v]的贡献
dp[v]=dp[u]+1+0.5*(size[u]-size[v]-1) (有U to V的一条边)
1 var head,vet,next,size:array[1..210000]of longint; 2 dp:array[1..110000]of double; 3 n,i,x,tot:longint; 4 5 procedure add(a,b:longint); 6 begin 7 inc(tot); 8 next[tot]:=head[a]; 9 vet[tot]:=b; 10 head[a]:=tot; 11 end; 12 13 procedure dfs1(u,pre:longint); 14 var e,v:longint; 15 begin 16 size[u]:=1; 17 e:=head[u]; 18 while e<>0 do 19 begin 20 v:=vet[e]; 21 if v<>pre then 22 begin 23 dfs1(v,u); 24 size[u]:=size[u]+size[v]; 25 end; 26 e:=next[e]; 27 end; 28 end; 29 30 procedure dfs2(u,pre:longint); 31 var e,v:longint; 32 begin 33 e:=head[u]; 34 while e<>0 do 35 begin 36 v:=vet[e]; 37 if v<>pre then 38 begin 39 dp[v]:=dp[u]+0.5*(size[u]-size[v]-1)+1; 40 dfs2(v,u); 41 end; 42 e:=next[e]; 43 end; 44 end; 45 46 47 begin 48 //assign(input,'cf696B.in'); reset(input); 49 //assign(output,'cf696B.out'); rewrite(output); 50 readln(n); 51 for i:=2 to n do 52 begin 53 read(x); 54 add(i,x); 55 add(x,i); 56 end; 57 dfs1(1,-1); 58 dp[1]:=1; 59 dfs2(1,-1); 60 for i:=1 to n do write(dp[i]:0:1,' '); 61 //close(input); 62 //close(output); 63 end.