题意:访问一颗树,在节点上记录访问时间,每次对儿子节点的访问是随机的,问每个节点被访问时间的期望
在每个子树中,可以发现每个节点cur ,dp[cur]=dp[fa]+f(cur);
f这个函数可以发现是把fa当根节点,得到的每个子节点的期望值,这个值跟这棵子树的节点数有关,答案是(num[fa]-num[cur]-1)/2+1
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define maxn 100009
using namespace std;
int father[maxn], head[maxn], next[6 * maxn], to[6 * maxn], n, tot[maxn], Tot = 1;
double ans[maxn];
void add (int u, int v)
{
to[++Tot] = v;
next[Tot] = head[u];
head[u] = Tot;
}
void dfs (int x, int fa)
{
father[x] = fa;
tot[x] = 1;
for (int i = head[x];i; i = next[i])
if (to[i] != fa)
dfs (to[i], x), tot[x] += tot[to[i]];
}
void calc (int x, int fa)
{
for (int i = head[x]; i; i = next[i])
if (to[i] != fa)
{
double cnt = (tot[x] - 1 - tot[to[i]]) / 2.0 + 1.0;
ans[to[i]] = cnt + ans[x];
calc (to[i], x);
}
}
int main ()
{
cin >> n;
int ta;
rep (i, 1, n - 1)
scanf ("%d", &ta), add (ta, i + 1), add (i + 1, ta);
memset (tot, 0, sizeof (tot));
dfs (1, -1);
ans[1] = 1.0;
calc (1, -1);
rep (i, 1, n - 1)
printf ("%.8f ", ans[i]);
printf ("%.8f\n", ans[n]);
return 0;
}