CF696B Puzzles 概率期望
有一棵树,共有 $N$ 个节点,他会使用下列 $DFS$ 算法对该树进行遍历:
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)
1是这棵树的根,Bob会从1出发,即运行dfs(1),现在他想知道每个点 starting_time的期望值
令 $f[i]$ 表示访问到 $i$ 时的期望时间.
那么,如果说直接由 $i$ 的父亲到 $i$ 的话,$f[i]=f[fa]+1$
但是,$fa$ 的儿子中除了 $i$ 都有可能在 $i$ 之前访问.
这个概率为 $\frac{1}{2}$ 即之前/之后.
所以,$f[i]=f[fa]+1+\frac{size[fa]-size[i]-1}{2}$
#include <bits/stdc++.h> #define N 100005 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,edges; double f[N]; int hd[N],to[N<<1],nex[N<<1],size[N]; void add(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void dfs1(int u,int ff) { size[u]=1; for(int i=hd[u];i;i=nex[i]) dfs1(to[i],u), size[u]+=size[to[i]]; } void dfs2(int u,int ff) { if(u!=1) f[u]=f[ff]+1.0+(double)(size[ff]-size[u]-1)/2.0; for(int i=hd[u];i;i=nex[i]) dfs2(to[i],u); } int main() { // setIO("input"); int i,j; scanf("%d",&n); for(i=2;i<=n;++i) { int ff; scanf("%d",&ff), add(ff,i); } dfs1(1,0); f[1]=1.0; dfs2(1,0); for(i=1;i<=n;++i) printf("%.1lf ",f[i]); return 0; }