虛樹,顧名思義就是虛構的樹,它是一種用來解決樹上問題的演算法,主要思想是只將原樹上必要的點和它們的最近公共祖先取出來,構成一棵虛樹,並保留他們在樹上的相對關係。
我們先來看一道題:
給定一棵n個點的樹,每次詢問給定乙個大小為k的點集,你需要切掉一些邊,使得點集中的點均不與1號點聯通,而每條邊都有被切掉所需的代價,你還要讓總代價最小。\(2 \leqslant n \leqslant 250000,,\sum ki \leqslant 500000,1 \leqslant k_i \leqslant n-1\)構建虛樹採取的思路是:將點「從左到右」地新增。
我們先要將樹遍歷一遍給每個點記乙個dfs序,然後將詢問點按dfs序排序。
用棧維護一條當前虛樹內「最靠右」的一條鏈,按順序加點。
假設當前準備加入的點為x,如果當前棧頂不是x的祖先,則彈棧,並向上乙個彈出的點(僅在本輪操作中)連邊,直到是或棧為空為止,順便記錄彈出的點與點x的最近公共祖先lca(彈出的所有點與點x的最近公共祖先一定相同)。
將lca與最後乙個彈棧的點連邊,之後再判斷lca是否已在棧頂,否則入棧。點x入棧。這樣棧中一定是「最靠右」的鏈。
複雜度\(o(klogn)\)
以下圖為例,綠色點表示詢問點,藍色點表示進入虛樹的點,紅色點表示棧裡的點。
加入2號點:
加入4號點:
加入6號點,2和4連邊:
加入9號點,2和6連邊、1和2連邊:
最後再將棧內的1和9連邊。
那麼我們回到原題,現在知道如何建虛樹了,如果解決問題?
首先我們要有乙個小技巧,就是對於乙個詢問點,如果某個詢問點是它的祖先,那麼就可以把它從詢問點中刪除。這樣詢問點之間就沒有祖先關係了。我們還需要為每個點記乙個值,為它到根(1號點)的路徑中最小代價的邊,記為\(v_x\)。
那麼建出虛樹後,我們對於虛樹中的葉子節點x,其dp值為\(v_x\)。對於非葉子節點x,dp值為\(min(v_x,\sum dp_)\),son為它的直系兒子,1號點的dp值即為最終答案。
提供乙個建虛樹的板子
這裡還有些用到虛樹的題,可供參考。
bzoj 3991 sdoi2015尋寶遊戲
bzoj 3611 heoi2014大工程
bzoj 3572 hnoi2014世界樹
luogu_4242 樹上的毒瘤
bzoj 5287 hnoi2018毒瘤
Virtual Tree 學習筆記
像大部分虛樹介紹一樣,以一道 爛大街 的例題 sdoi2011 消耗戰 引入 給定一棵大小為 n 的樹,每條邊有邊權,m 組詢問,每次詢問給定 k 個關鍵點,要求切斷 1 與所有關鍵點的路徑,求最小代價。2 leq n leq 2.5 times 10 5 m geq 1 sum leq 5 tim...
虛樹 Virtual Tree 學習筆記
description 在一場戰爭中,戰場由n個島嶼和n 1個橋梁組成,保證每兩個島嶼間有且僅有一條路徑可達。現在,我軍已經偵查到敵軍的總部在編號為1的島嶼,而且他們已經沒有足夠多的能源維繫戰鬥,我軍勝利在望。已知在其他k個島嶼上有豐富能源,為了防止敵軍獲取能源,我軍的任務是炸毀一些橋梁,使得敵軍不...
日常學習總結
關於vb中的把字串 日期型 數值型 賦值給某個變數的寫法 eg dim m1,r 此處我並不清楚 m1 到底是什麼型別 所以vb會自動匹配其應該所屬的型別,這是vb的一點強大之處 m select fitemid from t item where fitemclassid 3 and fnumbe...