?
?
?
因為上次比賽sb地把一道樹形dp當費用流做了,受了點刺激,用一天時間稍微搞一下樹形DP,今后再好好搞一下)
基于背包原理的樹形DP
poj 1947 Rebuilding Roads
題意:給你一棵樹,讓你求最少剪掉多少條邊可以剪出一棵點數為m的子樹.
解法:dp[i][j]表示i節點得到j個節點的子樹至少要剪多少邊,對于每個節點a和它的孩子b,如果剪掉b,則dp(s)[a][j]=dp(s-1)[a][j], 如果保留<a,b>dp(s)[a][j]=min{dp(s-1)[a][j - k] + dp[b][k]}.初始條件為dp[a][1] = 0;
為了不產生后效性,需要由大到小枚舉j的值。ans=min{dp[i][m] + 1,dp[root][m]}
?
[java] view plaincopy print?
void?dfs(int?a)?{??????????dp[a][1]?=?0;??????????for?(int?i?=?E[a];?i?!=?-1;?i?=?buf[i].ne)?{??????????????int?b?=?buf[i].be;??????????????dfs(b);??????????????num[a]+=num[b];??????????????for?(int?j?=Math.min(m,num[a]);?j?>?0;?j--)?{??????????????????dp[a][j]++;??????????????????for?(int?k?=?1;?k?<=?j&&k<=num[b];?k++)??????????????????????dp[a][j]?=?Math.min(dp[a][j],?dp[a][j?-?k]?+?dp[b][k]);??????????????}??????????}??????}?? void dfs(int a) {dp[a][1] = 0;for (int i = E[a]; i != -1; i = buf[i].ne) {int b = buf[i].be;dfs(b);num[a]+=num[b];for (int j =Math.min(m,num[a]); j > 0; j--) {dp[a][j]++;for (int k = 1; k <= j&&k<=num[b]; k++)dp[a][j] = Math.min(dp[a][j], dp[a][j - k] + dp[b][k]);}}}
?
?
poj 1155 TELE?
題意:其余點為轉發站。客戶端i愿支付的錢為pay[i],每條邊需要的花費固定,問電臺在保證不虧損的情況下,解法:dp[a][j] = Math.max(dp[a][j], dp[a][j - k] + dp[b][k]- buf[i].v);節點a給j個節點輸送信號能賺多少錢 j k num有N座城堡,每座城堡都有一定的寶物,允許攻克M個城堡并獲得里面的寶物。但有些城堡必須先攻克其他某一個特定的城堡才能攻克,問攻克M個城堡所獲得的最多寶物的數量。
dp
[a
][j
] = Math.max
(dp
[a
][j
], dp
[a
][k
] + dp
[b
][j
- k
]);dp[a][j]代表從i開始攻克j的城堡的最大獲利,初始化時dp[i][1]=i城堡內的寶貝數,dp[0][1]=0;dp[i][0]=0;ans=Max{dp[i][m],dp[0][m+1]};
------------------------------------------------------------------------------------------------------
?
Poj 2486 Apple Tree
題意:蘋果樹上有n個節點,每個節點數上有若干個蘋果,問最多走m步后至多能吃多少個蘋果。
解法:每個在路徑上的節點有兩種形態:一是以此節點為起點到達某點后不再返回,而是從此節點出發后返回再從其它孩子繼續走。因此定義dp[a][j][0]為a節點第一種情況下走j步的最大獲利dp[a][j][1]為a節點在第二種情況下走j步的最大獲利。轉移方程為:
?
dp
[a][j][0]=Math.max(dp[a][j][0],dp[a][k][1]+dp[b][j-k-1][0]); dp[a][j][0]=Math.max(dp[a][j][0],dp[a][k][0]+dp[b][j-k-2][1]); dp[a][j][1]=Math.max(dp[a][j][1],dp[a][k][1]+dp[b][j-k-2][1]) ?
初始化dp[i][0][1]=dp[i][0][0]=i節點的蘋果數。ans=Max{0,dp[1][i][0]};
?
Poj 1655 balancing Act/poj 3107?Godfather
題意:一個節點的平衡因子定義為:刪到此節點后形成的節點數最多的子樹。求一棵樹中平衡因子最大的節點。
解法,定義num[i]為i節點為根的子樹的節點數max[i]為i節點孩子節點數的最大值,一個節點的平衡因子=ans= Math.max(ans, first + second);
?
Sgu149&&HDU2196 Computer
解法:一個點的最遠路徑或者是向下一直走或者是先走到父節點然后再從父節點開始走一條較長的路徑。
? ? ?對于第一種情況由底向上更新求出每點的最長路徑和次長路徑即可;對于第二種情況,如果當前節點是父節點最長路徑上的點,那么向上的最長路徑=邊權+父節點的次長路徑,否則最長路徑=邊權+父節點的最長路徑。得到向上的最長路徑后更新最長路徑和次長路徑(如果更新了最長路徑,需要更新一下原來向下最大孩子的狀態,使它不是父節點最長路徑上的點),從上向下dfs更新一下即可。
[java] view plaincopy print?
int?dfs(int?a)?{??????????int?temp,?f?=?0;??????????for?(int?i?=?E[a];?i?!=?-1;?i?=?buf[i].ne)?{??????????????int?b?=?buf[i].be;??????????????temp?=?dfs(b)?+?buf[i].v;??????????????if?(temp?>?first[a])?{??????????????????second[a]?=?first[a];??????????????????first[a]?=?temp;??????????????????f?=?b;??????????????}??????????????else?if(temp>second[a])??????????????????second[a]=temp;??????????}??????????fid[a]?=?f;??????????isf[f]?=?true;??????????return?first[a];??????}????????void?work(int?p,?int?a,?int?v)?{??????????int?temp?=?-1;??????????if?(isf[a])??????????????temp?=?second[p]?+?v;??????????else??????????????temp?=?first[p]?+?v;??????????if?(temp?>?first[a])?{??????????????second[a]?=?first[a];??????????????first[a]?=?temp;??????????????isf[fid[a]]?=?false;??????????}?else?if?(temp?>?second[a])??????????????second[a]?=?temp;????????????????????for?(int?i?=?E[a];?i?!=?-1;?i?=?buf[i].ne)?{??????????????int?b?=?buf[i].be;??????????????work(a,?b,?buf[i].v);??????????}??????}?? int dfs(int a) {int temp, f = 0;for (int i = E[a]; i != -1; i = buf[i].ne) {int b = buf[i].be;temp = dfs(b) + buf[i].v;if (temp > first[a]) {second[a] = first[a];first[a] = temp;f = b;}else if(temp>second[a])second[a]=temp;}fid[a] = f;isf[f] = true;return first[a];}void work(int p, int a, int v) {int temp = -1;if (isf[a])temp = second[p] + v;elsetemp = first[p] + v;if (temp > first[a]) {second[a] = first[a];first[a] = temp;isf[fid[a]] = false;} else if (temp > second[a])second[a] = temp;for (int i = E[a]; i != -1; i = buf[i].ne) {int b = buf[i].be;work(a, b, buf[i].v);}}
轉載于:https://www.cnblogs.com/avcs/p/6909961.html
總結
以上是生活随笔為你收集整理的DP Intro - Tree DP Examples的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。