题目链接:
http://codeforces.com/problemset/problem/696/B
题意:
一个树,dfs遍历子树的顺序是随机的。所对应的子树的dfs序也会不同。输出每个节点的dfs序的期望
思路:
http://www.cnblogs.com/01world/p/5795498.html
假设四个子节点为A,B,C,D,因为排列等可能,所以A在B前面的概率跟A在B后面的概率相等,C和D对于A而言一样。所以遍历A的时间期望就是( t(B) + t(C) + t(D) )/2 + P。其中t(B)是访问B节点及其子树所需时间,尽管是随机排列,但是B子树中的节点树是确定的,所以t(B)可以确定,P是A的父节点访问时间的期望。
转移就是 dp[v]=dp[u]+1.0 + (sz[u]-sz[v]-1)/2.0 前面一部分是从父节点u直接走到v的期望,后面是前面走过了u的其它子节点到达v的期望
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define MS(a) memset(a,0,sizeof(a)) 5 #define MP make_pair 6 #define PB push_back 7 const int INF = 0x3f3f3f3f; 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 9 inline ll read(){ 10 ll x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 // 16 const int maxn = 1e5+10; 17 18 int n,sz[maxn]; 19 vector<int> g[maxn]; 20 double ans[maxn]; 21 22 void dfs1(int x){ 23 sz[x] = 1; 24 for(int i=0; i<(int)g[x].size(); i++){ 25 int v = g[x][i]; 26 dfs1(v); 27 sz[x] += sz[v]; 28 } 29 } 30 31 void dfs2(int u){ 32 for(int i=0; i<(int)g[u].size(); i++){ 33 int v = g[u][i]; 34 ans[v] = ans[u]+1 + (sz[u]-sz[v]-1)*1.0/2; 35 dfs2(v); 36 } 37 } 38 39 int main(){ 40 cin >> n; 41 for(int i=2; i<=n; i++){ 42 int x = read(); 43 g[x].push_back(i); 44 } 45 46 dfs1(1); 47 ans[1] = 1.0; 48 dfs2(1); 49 50 for(int i=1; i<=n; i++) 51 printf("%.1f ",ans[i]); 52 puts(""); 53 54 55 return 0; 56 }