标签:
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 a random 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 call dfs(1)).
Now Barney needs to pack a backpack and so he wants to know more about his upcoming journey: for every city i, Barney wants to know the expected value of starting_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 integer n (1 ≤ n ≤ 105) — the number of cities in USC.
The second line contains n - 1 integers p2, p3, ..., pn (1 ≤ pi < i), where pi is the number of the parent city of city number i in the tree, meaning there is a road between cities numbered pi and i in USC.
In the first and only line of output print n numbers, where i-th number is the expected value of starting_time[i].
Your answer for each city will be considered correct if its absolute or relative error does not exceed 10 - 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
题意:给你一棵树,然后用dfs随即给每个点标号,求每个点标号的期望;
思路:dfs+概率dp;
我们可以知道根节点的期望为1;
然后,他的子节点都是等概率的。
dp数组是各个节点的期望。
先给样例一的图:
我们写第二层的排列
1,1 2 4 5
2,1 2 5 4
3,1 4 2 5
4,1 4 5 2
5,1 5 2 4
6,1 5 4 2
所以节点2的期望为dp[1]+((1+size(4)+size(5))*2+size(4)+1+size(5)+1+1+1)/6;
根据这个我们先试着猜想dp[v]=dp[u]+1+(size(u)-size(v)-1)/2;
这就是状态转移方程;
我们先把上面到下面一层所必须加上一步先加上,也就是dp[u]+1;
然后我们可以知道下面所有的排列中,此节点的兄弟节点,要么排在这个节点之前要么之后,所一其他节点对于该节点的贡献为size()/2;
也就是排在前面和后面是等概率的;
复杂度O(n)
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<string.h> 5 #include<queue> 6 #include<stack> 7 #include<set> 8 #include<stdlib.h> 9 #include<vector> 10 using namespace std; 11 vector<int>vec[100006]; 12 long long cnt[100006]; 13 long long dfs1(int n); 14 double dp[100006]; 15 void dfs(int n); 16 int main(void) 17 { 18 int i,j,k; 19 while(scanf("%d",&k)!=EOF) 20 { 21 int n;memset(dp,0,sizeof(dp)); 22 for(i=0; i<100006; i++) 23 { 24 cnt[i]=0; 25 vec[i].clear(); 26 } 27 for(i=2; i<=k; i++) 28 { 29 scanf("%d",&n); 30 vec[n].push_back(i); 31 } 32 long long t=dfs1(1); 33 dp[1]=1.0; 34 dfs(1);printf("%.1f",dp[1]); 35 for(i=2; i<=k; i++) 36 { 37 printf(" %.1f",dp[i]); 38 } 39 printf("\n"); 40 } 41 return 0; 42 } 43 long long dfs1(int n) 44 { 45 long long sum; 46 int i,j,k; 47 for(i=0; i<vec[n].size(); i++) 48 { 49 cnt[n]+=dfs1(vec[n][i]); 50 } 51 cnt[n]+=1; 52 return cnt[n]; 53 } 54 void dfs(int n) 55 { 56 int i,j; 57 for(i=0; i<vec[n].size(); i++) 58 { 59 int x; 60 x=vec[n][i]; 61 dp[x]=dp[n]+1.0; 62 dp[x]+=1.0*(cnt[n]-cnt[x]-1)/2.0; 63 dfs(x); 64 } 65 }
D. Puzzles(Codeforces Round #362 (Div. 2))
标签:
原文地址:http://www.cnblogs.com/zzuli2sjy/p/5684267.html