CF123E Maze 期望 樹形dp

2021-09-01 15:49:56 字數 1594 閱讀 2412

題目鏈結

題目鏈結是洛谷翻譯過的。

題意:給你一棵樹,邊權都是1,每乙個點有乙個是起點的概率和乙個是終點的概率,你將以起點為根,開始在樹上隨機dfs,直到走到終點。求dfs從起點到終點的期望長度。n<=10w

題解:我們考慮一條確定路徑從s到t的期望步數的計算方法。我們發現,這個答案根據期望的線性性,我們可以拆成在這條路徑上每個點到下乙個點的期望步數之和。那麼我們考慮如何求乙個點到下乙個點的期望步數。

乙個點走到下乙個點的過程中,可能先走遍其中的某幾個子樹,然後再走到想要走的方向。我們假設當前點的度數為x

xx,那麼從當前點走到每乙個點的概率都是1

x\frac

x1​,而走進乙個子樹之後就會把整個子樹全部遍歷,由於去和回經過每條邊兩次,所以走到每個非目標點y

yy的貢獻都是1x∗

size

[y]∗

2\frac*size[y]*2

x1​∗si

ze[y

]∗2。由於我們隨機選取當前點能到達的沒有訪問過的點走,所以對於任意當前點能到達兩個點a

aa和b

bb,在隨機選擇點去走的情況下a

aa在b

bb前面和b

bb在a

aa前面的概率都是1

2\frac

21​,於是剛才的貢獻應該再乘1

2\frac

21​,那麼乙個非兩點在子樹的貢獻就是子樹大小乘當前點的度數。

對於這個題的做法,我們是列舉每乙個點作為終點時對答案的貢獻,考慮起點在每個點為根的子樹內的概率,我們其實由剛才的式子化簡可以得到,在某個子樹內的點的貢獻就是子樹大小,於是根據期望=概率*權值,以及期望的線性性,我們遍歷每個點能到達的點以及他們的子樹大小,然後乘概率和就是這個點的貢獻,最後答案是對每個點的答案求和。

**:

#include

using

namespace std;

int n,hed[

100010

],cnt,sz[

100010

],fa[

100010];

double ru[

100010

],chu[

100010

],sru,schu,ans;

struct node

a[200010];

inline

void

add(

int from,

int to)

inline

void

dfs(

int x)

}int

main()

for(

int i=

1;i<=n;

++i)

for(

int i=

1;i<=n;

++i)

ru[i]

/=sru;

dfs(1)

;for

(int x=

1;x<=n;

++x)

}printf

("%.12lf\n"

,ans)

;return0;

}

CF123E Maze(期望dp,樹形dp,式子)

題目鏈結 題目大意 給你一棵樹,邊權都是1,每乙個點有乙個是起點的概率和乙個是終點的概率,你將以起點為根,開始在樹上隨機dfs,每到乙個點,就會將他的所有兒子隨機打亂成序列,然後按照那個隨機順序走完,直到走到終點。求dfs從起點到終點的期望長度。其實一開始看到這個題,還是有點懵逼的啊 根據期望的線性...