樹形 dp 換根 dp

2022-05-11 04:28:22 字數 2510 閱讀 3206

樹形dp

樹形動歸一般是依賴於dfs的,根據動歸的後效性,父節點的狀態一般都依賴子節點的狀態以某種方式轉移而來

換根的p2015

\[設f[i][j]表示i的子樹上保留j條邊最多蘋果數\\

\]p2279

\[狀態表示f[x][0]:覆蓋到x的爺爺和x整棵子樹(向上2層),最少個數\\

f[x][1]:覆蓋到x的父親和x子樹(向上一層)\\

f[x][2]:覆蓋到x整顆子樹(向上0層)\\

f[x][3]:覆蓋x的兒子及其子樹(向上-1層)\\

f[x][4]:覆蓋所有x的孫子及其子樹(向上-2層)\\

顯然f[x][i]一定包含f[x][i+1],y.z是x的兒子\\

f[x][0]=1+\sum f[y][4](因為i可以覆蓋到向上2層,所以它自己必須是消防站~顯然)\\

x的兒子中有乙個一定覆蓋的爺爺,同時覆蓋到兄弟(因為y一定是選了),其他的兒子只需要覆蓋的自己的兒子即可\\f[x][1]=min(f[y][0]+\sum f[z][3](y!=z))\\

f[x][2]=min(f[y][1]+\sum[z][2])有乙個兒子覆蓋到父親,但無法覆蓋到y的兄弟,所以其他兒子要覆蓋到自己\\

f[x][3]=\sum f[y][2]讓每個兒子覆蓋到自己即可\\

f[x][4]=\sum f[y][3]讓每個兒子覆蓋到自己的兒子\\

\]p1122 最大子樹和

\[設f[i][0]為被當前這個點保安控制的點\\

顯然f[i][0]=\sum min(f[son[i]][0],f[son[i]][1],f[son[i][2])+val[i]\\

f[i][1]為被當前這個點的兒子控制的點\\

顯然f[i][1]=\sum min(f[son[i][0],f[son[i]][1])如果選擇的全部都是f[son[i]][1],\\要再加上min(f[son[i]][0]-f[son[i]][1])\\

f[i][2]為被當前這個點的fa控制的點\\

這個有點麻煩f[i][2]=\sum min(f[son[i]][0],f[son[i]][1])我們不妨這樣理解,對於i節點我們讓它\\的父親節點fa覆蓋它,那麼根據我們的狀態設計,此時必須要滿足以i的兒子son[i]為根的子樹\\之中所有點已經被覆蓋那麼這時就轉化為乙個子問題,要讓y子樹滿足條件,只有兩種決策:要麼son[i]\\被son[i]的兒子覆蓋,要麼被son[i]自己覆蓋(即選擇son[i]節點)\\,只需要在son[i]的這兩種狀態取min累加就可以了

\]對於\(f[i][1]\)的轉移,luogu大佬有詳細解釋:(這位大佬)\(\_\_\_new2zy\_\_\_\)

我們可以這樣理解,此時既然要保證x點是被自己的兒子覆蓋的,那麼如果此時y子樹已經滿足了全部被覆蓋,但是y此時被覆蓋的狀態卻是通過y節點自己的兒子達到的,那麼x就沒有被兒子y覆蓋到,那麼我們不妨推廣一下,如果x所有的兒子y所做的決策都不是通過選擇y點來滿足條件,那麼我們就必須要選擇x的乙個子節點y,其中y滿足\(f[y][0]-f[y][1]\)最小,並把這個最小的差值累加到\(f[x][1]\)中去這樣才能使得x點被自己的兒子覆蓋**,狀態\(f[x][1]\)也才能合理地得到轉移

就是這樣1代表選了該點,0沒選,假設問號為根節點,0為枝條,1為葉子,這樣顯然不行,所以取最小花費的點,加入到花費,明白了吧

0 0 0 0

1 1 1 1

//**哥哥:

#include#define maxn 1520

#define int long long

using namespace std;

inline int min(int a,int b)

while(c>='0'&&c<='9')

return f*p;}

struct edgee[maxn<<1];

int n,tot=0,head[maxn<<1],val[maxn];

int f[maxn][4];

inline void add(int x,int y)//加邊

inline int treedp(int u,int fa)

} treedp(1,0);

printf("%d",min(f[1][0],f[1][1]));

}

換根dp一般分為三個步驟

1、先指定乙個根節點

2、一次dfs統計子樹內的節點對當前節點的貢獻

3、一次dfs統計父親節點對當前節點的貢獻並合併統計最終答案

二次掃瞄與換根法:

\(f[i]表示以u為根的樹的深度和,size[i]表示以i為根子樹的結點個數\)

\(f[v]=f[u]-size[x]+n-size[x]=f[u]+n-2*size[x]\)

本來是以u為根的樹,變成以兒子v為根的樹,

那麼v的所有結點的深度都會減1,深度和就會減少size[v],

同樣地,所有不在v的子樹上的結點的深度都會+1,深度和就會加上n - size[v],

樹形DP 換根DP

某些樹形dp問題中,我們要求的值是類似 以當前節點為根節點得到的答案 卻沒有給出固定的根節點,若仍然按照常規的樹形dp思路對每個點進行dp,我們對每乙個節點均進行一次 dfs 最後的複雜度是 o left n 2 right 如果我們先假設任意乙個點為根進行 dp,求出當前樹形結構下以每個點為根的子...

樹形dp之換根dp

樹形dp之換根dp 換根dp是樹形dp這一類中我覺得比較難的一類。一般的樹形dp都只需要從子樹往父親推,然而換根dp則需要從父親往子樹推,接下來寫寫我學習換根dp的幾個例題。例題1 computer 題目大意 給你一棵樹,然後問你每乙個點具體其他點最遠的距離是多少。解題 這個題目首先任意找乙個點為根...

E Tree Painting 樹形dp 換根

題意 給定一棵樹,一開始點都是白色的,每次你可以對乙個點染色,獲得的分數就是當前點連線的只含白色的點的連通塊的點個數。輸出最多的分數。2 n 2 1 05 2 n 2 10 5 2 n 2 105分析 每次對乙個點進行操作就將樹分成了m棵子樹,並且我們肯定是先操作父節點,再操作子節點,所以自然就想到...