Barney lives in country USC (United States of Charzeh). USC hasn cities numbered from 1 through n and n - 1 roads between them. Cities and roads of USC form a rooted tree (Barney's not sure why it is rooted). Root of the tree is the city number1. Thus if one will start his journey from city 1, he can visit any city he wants by following roads.
Some girl has stolen Barney's heart, and Barney wants to find her. He starts looking for in the root of the tree and (since he is Barney Stinson not a random guy), he uses arandom DFS to search in the cities. A pseudo code of this algorithm is as follows:
let starting_time be an array of length n
current_time = 0
dfs(v):
current_time = current_time + 1
starting_time[v] = current_time
shuffle children[v] randomly (each permutation with equal possibility)
// children[v] is vector of children cities of city v
for u in children[v]:
dfs(u)
As told before, Barney will start his journey in the root of the tree (equivalent to calldfs(1)).
Now Barney needs to pack a backpack and so he wants to know more about his upcoming journey: for every cityi, Barney wants to know the expected value ofstarting_time[i]. He's a friend of Jon Snow and knows nothing, that's why he asked for your help.
The first line of input contains a single integern (1 ≤ n ≤ 105) — the number of cities in USC.
The second line contains n - 1 integersp2, p3, ..., pn (1 ≤ pi < i), where pi is the number of the parent city of city numberi in the tree, meaning there is a road between cities numberedpi andi in USC.
In the first and only line of output print n numbers, where i-th number is the expected value ofstarting_time[i].
Your answer for each city will be considered correct if its absolute or relative error does not exceed10 - 6.
7
1 2 1 1 4 4
1.0 4.0 5.0 3.5 4.5 5.0 5.0
12
1 1 2 2 4 4 3 3 1 10 8
1.0 5.0 5.5 6.5 7.5 8.0 8.0 7.0 7.5 6.5 7.5 8.0
题意:从节点1开始dfs,每次随机选个儿子继续dfs,求到达每个节点的经过节点的期望个数(包含该节点)。
思路:很显然,经过节点a一定经过父节点,必然与父节点有关,所以到达a节点的经过节点期望个数 = 到达a的父节点的经过节点的期望个数 + 从父节点(不包含父节点)到节点a的经过节点的期望个数。
而a的父节点到节点a,可能直接到达,也可能经过经过若干兄弟节点所在的子树再到达a,因此就可以根据在先到达节点a还是先经过兄弟节点b,想到到达节点a之前经过某一个兄弟节点b所在子树的概率为0.5。用num[a] 表示 节点a所在子树(包阔节点a)的节点个数,dp[a]表示到达节点a的经过节点的期望个数。那么状态转移方程就是:
dp[a]=dp[b]+(num[b]-num[a]-1)*0.5+1 ; //b代表a的父节点
详细见代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 1e5+100;
vector<int>G[maxn];
int num[maxn];
double ans[maxn];
int n;
void dfs(int a)
{
int i;
for(i=0;i<G[a].size();i++)
{
ans[G[a][i]]=ans[a]+(num[a]-num[G[a][i]]-1)*0.5+1;
dfs(G[a][i]);
}
}
int main()
{
scanf("%d",&n);
int i,j,a,b;
for(i=2;i<=n;i++)
{
scanf("%d",&a);
G[a].push_back(i);
}
for(i=n;i>=1;i--)
{
a=1;
for(j=0;j<G[i].size();j++)
a+=num[G[i][j]];
num[i]=a;
}
ans[1]=1.0;
dfs(1);
for(i=1;i<=n;i++)
printf("%.1f%s",ans[i],i==n ? "\n":" ");
return 0;
}