樹型動態規劃就是在「樹」的數據結構上的動態規劃,平時做的動態規劃都是線性的或者是創建在圖上的,線性的動態規劃有二種方向既向前和向後,相應的線性的動態規劃有二種方法既順推與逆推,而樹型動態規劃是創建在樹上的,因此也相應的有二個方向: 編程
不論是 從葉->根 仍是 從 根 - >葉,二者都是根據須要採用,沒有好壞高低之分。數據結構
用來作動態規劃也簡直是錦上添花再美不過的事,由於樹自己至少就有「子結構」性質(樹和子樹);自己就具備遞歸性。因此在樹上DP實際上是其所固然的事,相比線性動態規劃來說,轉移方程更直觀,更易理解。 spa
對於一棵n個結點的無根樹,找到一個點,使得把樹變成以該點爲根的有根樹時,最大子樹的結點數最小,即刪除這個點後最大連通塊的結點數最小。那麼這個點就是樹的重心。 3d
例題:題目大意:對於一棵無根樹,找到一個點使得樹以該點爲根的有根樹,最大子樹(選擇該節點後其子樹的最大節點)的節點數最小。blog
解法:任選一個結點爲根,把無根樹變成有根樹,而後設f[i]表示以i爲根的子樹的結點個數。遞歸
程序實現:一次DFS,在無根樹轉有根樹的同時計算。對於結點i,子樹中最大結點個數爲max{f[j]}個結點,i的「上方子樹」中有n-f[i]個結點,只需在dfs過程當中找到最大的子樹節點,並與其上方的節點數作比較,就能夠找出樹的重心了。搜索
補充性質: 程序
1.樹中全部點到某個點的距離和中,到重心的距離和是最小的;若是有兩個重心,那麼他們的距離和同樣。方法
2.把兩個樹經過一條邊相連獲得一個新的樹,那麼新的樹的重心在鏈接原來兩個樹的重心的路徑上 im
3.把一個樹添加或刪除一個葉子,那麼它的重心最多隻移動一條邊的距離
樹的直徑: 樹的直徑是指樹的最長簡單路。
例題:題目大意:對於一棵無根樹,找到樹的一條直徑。假設邊權爲1。
解法一:從任意一點u出發搜到的最遠的點必定是s、t中的一點,而後在從這個最遠點開始搜,就能夠搜到另外一個最長路的端點,即用兩遍廣搜就能夠找出樹的最長路。
解法二:算是樹的直徑的一個性質,樹的直徑的長度必定會是某個點的最長距離f[i]與次長距離g[i]之和。最後求出max{f[i]+g[i]}就能夠了。 令j是i的兒子,則:
一、若f[j]+dis[i][j]>f[i],則g[i]=f[i],f[i]=f[j]+dis[i][j];//最大值次大值被更新
二、不然,若f[j]+dis[i][j]>g[i],則g[i]=f[j]+dis[i][j];//次大值被更新
首先題意是在一棵樹T中輸出每一個結點到葉子的最遠距離;
首先第一個dfs求出全部每一個節點i在其子樹中的正向最大距離和正向次大距離和d[i][0]和d[i][1](若是i節點在子樹中最大距離通過了2號兒子,那麼次大距離就是不通過2號兒子的最大距離)。而且還要標記c[i]=j表示節點i在其子樹中的最大距離通過了節點j(即j是i的一個兒子)。
由上步咱們得到了正向最大距離,正向次大距離和最大距離的兒子節點標記。畫圖能夠知道咱們創建的這棵樹,i節點的最遠距離只有兩種選擇:i節點所在子樹的最大距離,或者i節點鏈接它的父節點所能到達的最大距離。
因此咱們只要求出反向最大距離d[i][2](即i節點往它的父節點走所能到達的最大距離)就能夠知道i節點在整個樹中能走的最大距離了。 d[i][2]求法:i節點往它的父節j點走,若是它的父節點的正向最大距離不通過i的話,那麼d[i][2]要不就是它父節點的反向最大距離+W[i][j]要不就是它父節點的正向最大距離+ W[i][j]. 若是它的父節點的正向最大距離通過i的話,那麼d[i][2]要不就是它父節點的反向最大距離+W[i][j]要不就是它父節點的正向次大距離+ W[i][j].
上面就是dfs2要求的值。最終f[i]=max(d[i][0],d[i][2])
普通的樹形DP中,經常會採用葉->根的轉移形式,根據父親的狀態,來肯定子節點的狀態,若子節點有多個,則須要一一枚舉,將子節點(子樹)的DP值合併。
P1352 沒有上司的舞會
題目描述
某大學有N個職員,編號爲1~N。他們之間有從屬關係,也就是說他們的關係就像一棵以校長爲根的樹,父結點就是子結點的直接上司。如今有個週年慶宴會,宴會每邀請來一個職員都會增長必定的快樂指數Ri,可是呢,若是某個職員的上司來參加舞會了,那麼這個職員就不管如何也不願來參加舞會了。因此,請你編程計算,邀請哪些職員可使快樂指數最大,求最大的快樂指數。
輸入輸出格式
輸入格式:
第一行一個整數N。(1<=N<=6000) 接下來N行,第i+1行表示i號職員的快樂指數Ri。(-128<=Ri<=127) 接下來N-1行,每行輸入一對整數L,K。表示K是L的直接上司。
輸出格式:
輸出最大的快樂指數。
經典的樹形dp
設f[x][0]表示以x爲根的子樹,且x不參加舞會的最大快樂值
f[x][1]表示以x爲根的子樹,且x參加了舞會的最大快樂值
則f[x][0]=sigma{max(f[y][0],f[y][1])} (y是x的兒子)
f[x][1]=sigma{f[y][0]}+h[x] (y是x的兒子)
先找到惟一的樹根root 則ans=max(f[root][0],f[root][1])
P2015 二叉蘋果樹
【問題描述】
有一棵蘋果樹,若是樹枝有分叉,必定是分2叉,這棵樹共有N個結點,編號爲1-N,樹根編號必定是1。 如今這顆樹枝條太多了,須要剪枝。可是一些樹枝上長有蘋果。給定須要保留的樹枝數量,求出最多能留住多少蘋果。
【樣例輸入】
5 2
1 3 1
1 4 10
2 3 20
3 5 20
【樣例輸出】
21
【思路點撥】
須要保留Q條樹枝,即保留j=Q+1個結點。分三種狀況討論:
①所有保留右子樹中的j-1個結點;//根結點必須保留
②所有保留左子樹中的j-1個結點;
③左子樹保留k個結點,則右子樹保留j-k-1個結點。
設樹根爲i,左兒子爲l[i],右兒子爲r[i],對於①狀況,要取得該方案的最大值,須要取得以r[i]爲根的子樹保留j-1個結點的最大值。②③同理。
f[i][j]:以i爲根的樹上保留j個節點的最大權值和。
狀態轉移方程:
初始化:
目標: