题意:
对一棵树进行dfs,求每个点访问次序的期望。
解:
对于父节点为x的子结点y1,y2,y3…yn
E[yi]=E[x]+1+f(yi)
f(yi)=p(0)E′(0)+p(1)E′(1)+p(2)E′(2)+...+p(n−1)E′(n−1)
( E′(i) 代表有i个兄弟结点在y结点之前访问)
f(yi)=1n∗(E′(0)+E′(1)+E′(2)+...+E′(n−1))
其中 E′(0)=0,
E′(1)=1C1n−1∗sum(y1)+1C1n−1∗sum(y2)+…+1C1n−1∗sum(yn)
(不包含sum(yi)项,sum(yi)代表yi为根的树大小)
=1C1n−1∗∑j≠isum(yj)
E′(2)=C1n−2C2n−1∗∑j≠isum(yj)
=2n−1∗∑j≠isum(yj)
E′(k)=Ck−1n−2Ckn−1∗∑j≠isum(yj)
=kn−1∗∑j≠isum(yj)
所以f′(yi)=1n∗0+1+2+...+n−1n−1∗∑j≠isum(yj)
=1n∗(n−1)∗n2∗(n−1)∗∑j≠isum(yj)
=12∑j≠isum(yj)
E[yi]=E[x]+1+12∑j≠isum(yj)
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s) memset(a,x,(s)*sizeof a[0])
#define mem(a,x) memset(a,x,sizeof a)
#define ysk(x) (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn= 100000 ;
int n;
int fir[maxn+10],nex[2*maxn+10],to[2*maxn+10],nedge;
double ans[maxn+10];
int dp[maxn+10];
double E[maxn+10];
void add_edge(int x,int y)
{
to[nedge]=y;
nex[nedge]=fir[x];
fir[x]= nedge++;
}
void dfs(int x)
{
dp[x]=1;
for(int i=fir[x];~i;i=nex[i])
{
int y=to[i];dfs(y);
dp[x]+=dp[y];
}
}
void dfs2(int x)
{
for(int i=fir[x];~i;i=nex[i])
{
int y=to[i];
E[y]=E[x]+1+ (dp[x]-1.0-dp[y] )/2;
dfs2(y);
}
}
int main()
{
std::ios::sync_with_stdio(false);
int x;
while(cin>>n)
{
nedge=0;
mes(fir,-1,n+1);
for(int i=2;i<=n;i++)
{
cin>>x;
add_edge(x,i);
}
E[1]=1;
dfs(1);
dfs2(1);
for1(i,n) printf("%.10f%c",E[i],i==n?'\n':' ');
}
return 0;
}