【CF696B】Puzzles(树形DP,期望)

题意: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.

    

原文地址:https://www.cnblogs.com/myx12345/p/6062428.html