題目描述
給出一棵包含
行走的僞代碼如下:
count = 0
bool DFS( x, fa )
if ( x==v ) return 1
random_shuffle(e[x])
for each y in e[x] // which means that all the order of has the same possibility to be chosen
++count
if ( DFS( y, x ) ) return 1
++count
return -1
DFS( u, -1 )
要求實現
- 在
x 與y 之間修建一條道路,若此前x 與y 之間有路徑相連則無視此次操作 - 若
x 與y 之間存在一條直接相連的道路,則去掉之 - 詢問從
u 走到v 的期望步數
分析
首先分析一下要求的期望步數是個什麼東西。
讀懂僞代碼後發現它實際上是一個按照隨機順序遍歷這棵樹,直到遇到終點。
假如我們某一步走了岔路,那麼顯然要遍歷完這條岔路對應的整一棵子樹。那麼在每一個點上我們只關注終點所在子樹,以及它之前遍歷的有哪一些子樹。
不妨記
從總體來看,
注意這一項
由於這裏取遍所有的滿足
- 當
k=0 時,分子爲0 - 當
k=1 時,分子爲2sizex¯¯¯¯¯¯¯¯ - 當
k=2 時,分子爲4sizex¯¯¯¯¯¯¯¯ ⋯ - 當
k=m 時,分子爲2msizex¯¯¯¯¯¯¯¯
於是這一項實際上是
總的那一項,實際上就是以
所以我們需要維護的東西就很明確了
- 子樹大小
- 連通性
- 支持動態加或刪邊
用LCT可以輕鬆解決後兩個問題。
但是LCT怎麼維護子樹大小呢?
不妨記
- 在
access 時,有可能將一個虛兒子變成重兒子,此時需要對extra 和link 做出一些調整 - 在
splay 時需要對extra 做出一些調整 - 加邊時需要對
extra 做出一些調整 - 刪邊時需要對
link 做出一些調整
剩下任意的操作都不會對
於是子樹大小求出來了,剩下的就是LCT的常規維護了。
時間複雜度
空間複雜度