1. 程式人生 > >Codeforces.280C.Game on Tree(期望)

Codeforces.280C.Game on Tree(期望)

AI tails pre include har getchar fin line isp

題目鏈接

參考:淺談期望的線性性(可加性)
Codeforces 280C Game on Tree 概率dp 樹上隨機刪子樹 求刪完次數的期望(這個的前半部分分析並沒有看。。)

\(Description\)
給你一棵有\(n\)個白點的有根樹,每次隨機選擇一個點,將它和它的子樹中所有點染黑。
問期望操作多少次後所有點都被染黑?

\(Solution\)
期望好玄啊。。(好吧是我太弱)
因為概率具有可加性,一棵樹可以分解為多棵子樹,而子樹分解的最終狀態就是點,所以我們可以計算每個點的期望操作次數再求和,即\[E(總操作次數)=E(每個點被選中操作次數)\]
這個期望操作次數是指作為白點被選中染黑的期望次數。

因為一個點祖先節點被染黑後,這個節點操作次數就為0了,所以得出一個點x的期望E(x)=1/dep[x].
直接DFS。。

//62ms  9872KB
#include <cstdio>
#include <cctype>
#define gc() getchar()
const int N=1e5+5;

int n,Enum,H[N],nxt[N<<1],to[N<<1];
double Ans;

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for
(;isdigit(c);now=now*10+c-'0',c=gc()); return now; } inline void AddEdge(int u,int v) { to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum; to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum; } void DFS(int x,int f,int d) { Ans+=1.0/d; for(int i=H[x]; i; i=nxt[i]) if(to[i]!=f) DFS(to[i],x,d+1
); } int main() { n=read(); for(int u,v,i=1; i<n; ++i) u=read(),v=read(),AddEdge(u,v); DFS(1,1,1); printf("%.10lf",Ans); return 0; }

Codeforces.280C.Game on Tree(期望)