Codeforces 696B. Puzzles (概率DP求期望)

来源:互联网 发布:ubuntu ssd 优化 编辑:程序博客网 时间:2024/06/05 04:51

题目链接

简单题意

访问一颗树,在节点上记录访问时间,每次对儿子节点的访问是随机的,问每个节点被访问时间的期望

思路

很显然,如果先访问了兄弟节点,则会把兄弟节点的子树全部访问完成后再来下一次选择。所以要记录一下每个节点中子节点的个数,这个很简单,直接倒着扫一遍邻接表就累加行了。有了子节点的个数,我们还需要得到某一个节点先于其他节点被选择的概率,是0.5

简单说明一下,例如某个节点有a,b,c,d四个子节点,则可能产生24种排列,在所有的排列中,任意一点先于另外一点的概率是0.5,所以对于任意一个点,他先于另外某一个点被访问的概率是0.5。

没有被选中额外花费的时间为父亲的所有子节点数,减去当前节点及其子节点数。

所以得到转移方程为(i是父亲节点,to是儿子结点)
ans[to] = ans[i] + 1 + (sz[i]-1-sz[to]) * 0.5

代码

n = int(input())pos,tree,ans,sz = list(map(int,input().split())) if n > 1 else [],[],[],[]for i in range(n):  tree.append([])  ans.append(0.0)  sz.append(0)for i in range(n-1):  tree[pos[i]-1].append(i+1)for i in range(n)[::-1]:  sz[i] = 1  for to in tree[i]:    sz[i] += sz[to]for i in range(n):  for to in tree[i]:    ans[to] = ans[i] + 1 + (sz[i]-1-sz[to]) * 0.5st = lambda i: str(i+1)print(' '.join(list(map(st,ans))))
0 0
原创粉丝点击