Hile每日演算法 3 31 樹形dp之換根法

2021-10-04 15:10:52 字數 2682 閱讀 4477

周二週三真的太難了,有早課導致不能熬夜,於是就只能趁著中午的時間寫一寫,這幾天先寫點簡單的東西,就當重新複習了,應該算是給初學者的知識普及,其他的過了週三再說。

首先來講一下樹的重心

樹的重心,即 樹上到所有點的距離之和最小/以此為根深度最小/最大子樹大小最小 的點,具有很多方便的性質,如:

1.當一棵樹新增/刪除乙個節點,樹的重心最多移動乙個位置。(動態維護)(19icpc徐州m題,so~no~chi~no~sa~da~me~)

2.當兩棵樹通過某點連線在一起形成新樹時,新樹的重心一定在連線兩棵舊樹重心的路徑上。(兩樹合併)

3.以一顆樹的重心為根,劃分的子樹大小一定不超過原樹的一半。(樹分治)

眾所周知,回字有四種寫法,門前有兩棵棗樹,重心也有兩種求法(通常情況下),一種是兩遍dfs找樹上最長路徑的中點,一種就是今天要講的內容——樹形dp之換根法。

首先,初始是不知道重心所在的,最直接的方法就是列舉每個點作為重心的情況。由上面重心的定義可以知道,重心一定是最大的子樹大小最小的點。因此,我們不妨先把1

11作為根,設s[i

]s[i]

s[i]

為以1

11為根時子樹i

ii的大小,根據dfs的性質,子樹遍歷結束的時候,其s[i

]s[i]

s[i]

也被更新完了,所以,一次從1

11開始的dfs就可以求出所有點的子樹大小。

如果我們用f[i

]f[i]

f[i]

來表示以i

ii為根的最大子樹大小,根據上述演算法,dfs結束後可以求出f[1

]=ma

x(s[

son]

)f[1]=max(s[son])

f[1]=m

ax(s

[son

])。此時,如果根從1

11換到了1

11的子節點上,f[i

]f[i]

f[i]

該如何變化呢?

f [i

]=ma

x(s[

son]

,n−s

[i])

f[i]=max(s[son],n-s[i])

f[i]=m

ax(s

[son

],n−

s[i]

)這裡滿足了動態規劃的三要素:狀態邊界條件轉移方程

更具體地說,要在樹上所有的點中找到滿足條件的根,就要確定隨根變化的資料(狀態)、初始當根為1

11的情況(邊界條件)、根從上往下移動的變化**移方程)。

來一道題感受一下:

cf1187e tree painting

題意:給定一棵所有結點初始為白色的樹,第一回合選擇任意乙個白點塗黑,接下來每次都選和黑點鄰接的白點塗黑,每次(包括第一次)選點時會獲得這個點所在的白點連通塊大小的分數,求可能獲得的最大分數。

這就是換根法的直接應用了。第乙個塗黑的點就相當於選乙個根,然後沿著根往下走。假設以1

11為根,s[i

]s[i]

s[i]

表示i

ii的子樹大小,1

11為根時的答案ans

1ans_1

ans1

​即為∑i=

1ns[

i]

\sum_^ns[i]

∑i=1n​

s[i]

。當根由u

uu變為v

vv時,ans

v=an

su−s

[v]+

(s[1

]−s[

v])=

ansu

−2∗s

[v]−

s[1]

ans_v=ans_u-s[v]+(s[1]-s[v])=ans_u-2*s[v]-s[1]

ansv​=

ansu

​−s[

v]+(

s[1]

−s[v

])=a

nsu​

−2∗s

[v]−

s[1]

。a ns

ians_i

ansi

​的最大值就是答案。

#include

#define n 200010

#define ll long long

using

namespace std;

int n;

vector<

int> g[n]

;ll sum[n]

,ans,s;

void

dfs1

(int u,

int fa)

s+=sum[u];}

void

dfs2

(int u,

int fa,ll s)

intmain()

dfs1(1

,0);

dfs2(1

,0,s);

cout<}

睡眠時間不夠,ddl到了作業也沒做,導致這次寫的比較倉促,內容也不是很詳盡,還好演算法並不複雜。明、後兩天準備寫一寫數論基礎,尤其是數學角度的推理過程(好像我也不怎麼擅長這些)。

每日演算法 計數DP和遞推DP

計數pd就是emm感覺求那種什麼路徑和的就是計數那一類的,再概括一下就是可以不用其他操作直接將它相鄰或者說符合要求的 求和,就是下乙個位置的值。回到這題 用動規很好做。我們想要知道 0,0 到終點的位置的路徑,只需要知道終點已左終點已下的路徑為多少就行了。dp i j 0,0 到 i,j 位置的路徑...

演算法訓練 結點選擇 樹形DP

問題描述 有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?輸入格式 第一行包含乙個整數 n 接下來的一行包含 n 個正整數,第 i 個正整數代表點 i 的權值。接下來一共 n 1 行,每行描述樹上的一條邊。...

每日一題 POJ 2486 樹形dp 樹上揹包

並不難寫,關鍵是要想清楚。樹形dp的第乙個比較完整寫完的題,是比較經典的題,來紀念一下。一開始沒想清楚是因為對揹包問題的滾動陣列優化的理解不夠,自然在樹上的問題也沒思考清楚。同時因為每個case過後忘記清零,導致re了一發,以後需要注意。dpr是回到該點,nr是不回到該點,轉移方程如 ac 耗時18...