有一棵n個節點的樹,樹上每個節點有乙個值,選擇m個節點使這些節點值的和最大
要求:如果選當前節點,則必須選它的父節點
我們設dp[i][j]為以i為根的樹上留j個節點的最大值,轉移方法如下
for(int j=min(q,size[x]);j>1;j--)複雜度o(n*m^2)}
有一棵n個節點的樹,樹上每個節點有乙個代價和乙個價值,選擇若干個節點使這些節點的價值最大並且代價不超過m
要求:如果選當前節點,則必須選它的父節點$n\le 5000,m\le 10000$
如果還像上一題那樣考慮的話,dp[i][j]為以i為根的子樹代價為j的最大價值,
共有m*n個狀態,每個狀態o(m)轉移,複雜度o(m*m*n),雖然達不到那麼高,但也一定會超時
考慮優化
首先將所有節點後序遍歷,p[i]儲存dfs序為i的節點編號,
l[i]儲存在i節點的子樹之前遍歷的最後乙個dfs序,如下圖
節點右側的為節點的dfs序,左上角的為l的值:
如p[4]=7,l[7]=3代表7號節點dfs序為4,在7節點的子樹之前遍歷的最後乙個dfs序為3
然後將dp[i][j]的意義改為前i個遍歷的節點代價為j的最大值
dp[i][j]=max(dp[l[u]][j](當前節點不選,則子樹都不能選),dp[i-1][j-v[u]]+w[u](選當前節點)) 注:u=p[i];
於是狀態轉移變成o(1)了,時間複雜度o(n*m)
只需將dp[i][j]的意義改為前i個遍歷的節點留j個的最大值即可,其他轉移都一樣
樹形dp 時間戳優化
姑且叫做時間戳優化吧 我們會遇到一類問題 給你一棵n 5000的樹,要在樹上跑樹形dp。我們可以輕鬆的想出dp的定義式,第一維是代表節點,第二維是題目要維護的資訊。範圍均是5000。如果我們暴力去跑的話,對於每個節點都要列舉所有子節點,並且第二維要列舉當前節點的值和子節點的值。這樣效率是o n 3 ...
樹形DP 樹形DP四例
是時候練一下dp了!我的題單 portkey f u,if fu,i 表示以u uu為根節點的子樹中保留i ii條樹枝的最大蘋果數 f u,i max f max f fu,i max這些題是菜,但也不能輕視啊!include using namespace std define in read i...
長鏈剖分優化樹形dp
apio鐵牌告辭 開場想打暴力然後gedit碼 5個小時沒寫完三題最低檔暴力真是快樂 聽課也就學到了一丟丟這個東西。模板題 首先k級兄弟可以一遍dfs的時候丟到k級父親上變成求k級孩子的詢問。求k級孩子有個很簡單的做法,直接dfs的時候維護掃到某個點時記錄下的每種dep出現次數,對於所有求這個點k級...