題目鏈接:http://codeforces.com/contest/697/problem/D
給出一顆樹的描述,從根節點開始,以DFS序遍歷。每次隨機走向當前節點的兒子節點,沒有子節點的時候就回溯。問遍歷到樹中每個點的期望步數。
考慮某一層DFS,假設我們已經求出該層根節點Root的答案ans[Root]。求該層x節點的答案。對於其他的節點有1/2的概率會排在該節點前面,對ans[x]的貢獻就爲該節點u的子樹大小的1/2。那麼ans[x] = ans[Root] + (size[Root]-size[x]-1]/2 + 1。
即 ans[x] = ans[Root] + (size[Root]-size[x])/2 + 1/2。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int head[maxn], tot;
int sz[maxn];
struct Edge{
int to, nx;
Edge(){}
Edge(int t){
to = t;
}
}e[2*maxn+1];
double dp[maxn];
int dfs(int u, int pre){
sz[u] = 1;
for (int k = head[u]; k != -1; k = e[k].nx){
int to = e[k].to;
if (to == pre) continue;
sz[u] += dfs(to, u);
}
return sz[u];
}
void getans(int u, int pre){
for (int k = head[u]; k != -1; k = e[k].nx){
int to = e[k].to;
if (to == pre) continue;
dp[to] = dp[u] + 0.5 + (sz[u]-sz[to])*(1.0/2);
getans(to, u);
}
}
void addEdge(int from, int to){
e[++tot] = Edge(to);
e[tot].nx = head[from];
head[from] = tot;
}
int main(){
memset(head, -1, sizeof(head));
tot = 0;
int n;
cin >> n;
for (int i = 2; i <= n; i++){
int to;
cin >> to;
addEdge(i, to); addEdge(to, i);
}
dfs(1, 1);
dp[1] = 1.0;
getans(1, 1);
for (int i = 1; i <= n; i++)
printf("%.1f", dp[i]), printf((i==n ? "\n" : " "));
return 0;
}