1. 程式人生 > >CF696B Puzzles 期望

CF696B Puzzles 期望

algorithm bin for color fin str ios || getc

技術分享圖片

顯然可以樹形$dp$

令$f[i]$表示$i$號節點的期望時間戳

不妨設$fa$有$k$個子節點,對於$i$的子節點$u$,它是第$j(1 \leqslant j \leqslant k)$個被訪問的概率是相同的,為$\frac{1}{k}$

當它作為第$j$個子節點被訪問時,需要從剩下的$k - 1$個節點中挑出$j - 1$個放到它前面,對每種情況的$sz$和取期望

考慮貢獻法

一個節點$v$,會給第$j$個被訪問的節點的貢獻次數為$\binom{k - 2}{j - 2}$

總的貢獻次數為$\binom{k - 1}{j - 1}$

因此,第$v$個節點對第$j$個被訪問的節點的貢獻為$\frac{j - 1}{k - 1} * sz[v]$

也就是說$u$節點在所有情況下需要被耽誤的時間應該為$\sum\limits_{1 \leqslant i \leqslant k} \frac{i - 1}{k - 1} * \sum sz[v]$

其中,$v$表示除了$u$以外的所有子節點

化簡一番,也就是$f[v] = f[fa] + 1 + \frac{1}{2} * \sum sz[v]$

$O(n)$即可

#include <map>
#include <set>
#include <queue>
#include <vector>
#include <cstdio>
#include 
<cstring> #include <iostream> #include <algorithm> namespace remoon { #define de double #define le long double #define ri register int #define tpr template <typename ra> #define rep(iu, st, ed) for(ri iu = st; iu <= ed; iu ++) #define drep(iu, ed, st) for(ri iu = ed; iu >= st; iu --) #define
gc getchar inline int read() { int p = 0, w = 1; char c = gc(); while(c > 9 || c < 0) { if(c == -) w = -1; c = gc(); } while(c >= 0 && c <= 9) p = p * 10 + c - 0, c = gc(); return p * w; } } using namespace std; using namespace remoon; #define sid 300050 de f[sid]; int n, sz[sid]; vector <int> son[sid]; inline void dfs(int o, int fa) { sz[o] = 1; for(auto cur : son[o]) dfs(cur, o), sz[o] += sz[cur]; } inline void dfs(int o) { for(auto cur : son[o]) { f[cur] = f[o] + 1 + (sz[o] - sz[cur] - 1) / 2.0; dfs(cur); } } int main() { n = read(); rep(i, 2, n) son[read()].pb(i); dfs(1, 0); f[1] = 1; dfs(1); rep(i, 1, n) printf("%lf ", f[i]); return 0; }

CF696B Puzzles 期望