題目鏈結
因為辣雞csdn,導致之前快寫好的部落格沒了
qwq悲傷逆流成河qwqqq
首先虛樹,這個東西,我感覺是一種思想,或者是方法,而並不是乙個資料結構什麼的。
他主要是用來解決:給出一棵樹,每次詢問選擇一些關鍵點,求一些資訊。
這些資訊的特點是,許多未選擇的點可以通過某種方式剔除而不影響最終結果。
於是就有了建虛樹這個演算法。我們根據原樹的資訊重新建樹,這棵樹中要盡量少地包含非關鍵節點。 這棵樹就叫做虛樹。這棵虛樹包含任意兩個關鍵節點的lca。
通常這類題o(n
m)
o(nm)
o(nm)會t
tt飛,而o(∑
詢問點個
數)
o(\sum 詢問點個數)
o(∑詢問點
個數)是能跑得過的qwq
那我們應該怎麼構造虛樹呢qwq我們把所有關鍵點按照dfs序排好序。
然後,虛樹要有乙個根。這裡一般直接把1號節點設為根。構建虛樹的主要過程就是使用乙個棧,維護從根開始的一條鏈。這條鏈上的所有點的dfs序一定是遞增的。
我們把關鍵點掃瞄一遍,一邊維護這個棧一邊連邊構建虛樹。
具體來說:
1.把根節點放入棧中2.把所有關鍵點點掃一遍。設當前的節點為x
xx,棧頂(鏈末端)的節點為y
yy。求出x
xx和y
yy的lca
lcalc
a。此時有2種情況。
1)lc
alca
lca為y
yy。此時x
xx在y
yy子樹內。我們就把x
xx壓入棧,相當於直接把x
xx新增到這條鏈的末尾。
2)x ,y
x,yx,
y分立在lca
lcalc
a的兩個子樹中。此時y這個子樹中的所有關鍵點一定都被遍歷過了。(原因:設有一關鍵點a在y子樹中,沒有被遍歷過。則dfn
[y
] n[a] n[x] dfn[y]df n[y] n[a] n[x] 。但是我們是把關鍵點按照dfs序來排的,a一定在x之前被掃) 因此y子樹內的所有關鍵點都已經被被加入虛樹。接下來我們要把y −>lc ay->lca y−>lc a這一段的點加入虛樹。我們設棧頂的節點為y yy,棧頂的第二個節點為zzz。 重複以下操作: 1.若dfn [z ]>df n[lc a] dfn[z]>dfn[lca] dfn[z] >df n[lc a]直接連邊z −> yz->y z−> y,然後把y yy出棧。 2.若dfn [z]= dfn[ lca] dfn[z]=dfn[lca] dfn[z] =dfn [lca ]這意味著z zz就是lca lcalc a。直接連邊lca −> ylca->y lca− > y。此時子樹已構建完畢。 3.若dfn [z ]>df n[lc a] dfn[z]>dfn[lca] dfn[z] >df n[lc a],說明lca lcalc a被yy y和zz z夾在中間。此時我們必須要把lca lcalc a加入虛樹,所以連邊lca −> ylca->y lca− > y,然後把y yy彈出棧,把lca入棧。然後子樹構造完畢。 最後把棧裡面的元素搞一搞,每次add edge (s[t op−1 ],s[ top] )addedge(s[top-1],s[top]) addedg e(s[ top− 1],s [top ])即可感覺配合**會比較好理解 solve() else else}} }if(sta[top] !=a[i] ) sta[ ++top] =a[i];} while (top>1) }那麼剩下的主要就是dpdp dp部分了首先,我們定義mn[ x] mn[x] mn[x ]表示在原樹上1到x 1到x1到 x的路徑上邊權的最小值,f[x ]f[x] f[x] 表示切割完x xx子樹內所有關鍵點的最小花費。 對於當前點x xx,如果他是關鍵點,那麼必須切割這個點到1的路經上的一條邊,那麼就是mn[ x] mn[x] mn[x ],否則f[x ]=mi n(mn [x], ∑f[s on ]f[x]=min(mn[x],\sum f[son] f[x]=m in(m n[x] ,∑f[ son] 上**void
intdp(
int x,
int flag)
if(tag[x]
==flag)
return
min(sum,mn[x]);
}其中有乙個要注意的地方就是虛樹的時候,因為每次要重新建樹,所以要清空poi
nt
point
poin
t陣列,而由於時間原因,又不能直接mem
se
tmemset
memset
,所以我們只能使用奇妙的手段!自殺式遍歷通過取位址,不斷修改poi
nt
point
poin
t
for
(int
&i=point[x]
;i;i=nxt[i]
)
由於宕機了三次qwq
所以暫時沒有辦法放整個題的**
虛樹 P2495 SDOI2011 消耗戰
好久沒有學習新的知識了。今天我學習了一下虛樹。虛樹就是乙個不存在的樹。用來簡化問題。它只包括一些關鍵點和他的lca 我們來看看上面這一道題 給出一棵樹,含有邊權。每次詢問給出k個點,然後詢問每個點與根斷開的最小代價。因為資料的關係肯定沒法直接dp過去的。首先我們可以發現可以與根到其他點的路徑沒有關係...
P2495 SDOI2011 消耗戰 虛樹
這是我做的第一道虛樹題啊,趕腳不錯.其實虛樹也沒什麼奇怪的,就是每棵樹給你一些點,讓你多次查詢,但是我不想每次都o n 所以我們每次針對給的點建一棵虛樹,只包含這些點和lca,然後在這棵虛樹上進行樹形dp,維護每個點的最小連邊權值,這樣的複雜度就會降低不少.這裡我寫了兩種寫法 其實都是抄的 一種是正...
P2495 SDOI2011 消耗戰 虛樹
題意 一棵樹上給定點集,求到根的最小割。每次詢問只和給定的點集以及它們的lca有關係,那麼把這些點拿出來建立一棵樹。再進行樹dp。具體操作把所有詢問點按照dfn排序,再用乙個棧進行維護建樹。彈棧的時候並不是每個點都和棧中第二個元素連邊,有可能最後乙個彈棧點和新的lca連邊。dp轉移時需要查詢樹鏈的最...