樹形DP(超詳細!!!)

1、概念

一、什麼是樹型動態規劃 

樹型動態規劃就是在「樹」的數據結構上的動態規劃,平時做的動態規劃都是線性的或者是創建在圖上的,線性的動態規劃有二種方向既向前和向後,相應的線性的動態規劃有二種方法既順推與逆推,而樹型動態規劃是創建在樹上的,因此也相應的有二個方向:      編程

  1. 葉->根:在回溯的時候從葉子節點往上更新信息    
  2. 根 - >葉:每每是在從葉往根dfs一遍以後(至關於預處理),再從新往下獲取最後的答案。    

不論是 從葉->根 仍是 從 根 - >葉,二者都是根據須要採用,沒有好壞高低之分。數據結構

二、樹真的是一種特別特別優美的結構!

用來作動態規劃也簡直是錦上添花再美不過的事,由於樹自己至少就有「子結構」性質(樹和子樹);自己就具備遞歸性。因此在樹上DP實際上是其所固然的事,相比線性動態規劃來說,轉移方程更直觀更易理解spa

三、難點    

  1. 和線性動態規劃相比,樹形DP每每是要利用遞歸+記憶化搜索。    
  2. 細節多,較爲複雜的樹形DP,從子樹,從父親,從兄弟……一些小的要處理的地方,腦子不清晰的時候作起來頗爲噁心    
  3. 狀態表示和轉移方程,也是真正難的地方。作到後面,樹形DP的老套路都也就那麼多,難的仍是怎麼能想出轉移方程,各類DP作到最後都是這樣!

2、經典問題

【樹的重心/質心】

對於一棵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])

 

2、普通樹形DP

普通的樹形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個節點的最大權值和。

狀態轉移方程:

初始化:

目標:

 

 

相關文章
相關標籤/搜索