B Zero Tree 思維 樹形dp

2021-10-09 10:17:31 字數 1593 閱讀 3774

題目描述

一棵樹是乙個有n個節點與正好n-1條邊的圖;並且符合以下條件:對於任意兩個節點之間有且只有一條簡單路徑。

我們定義樹t的子樹為一棵所有節點是樹t節點的子集,所有邊是t邊的子集的樹。

給定一顆有n個節點的樹,假設它的節點被編號為1到n。每個節點有乙個權值,v_ivi​表示編號為i的節點的權值。你需要進行一些操作,每次操作符合以下規定:

- 在給定的這棵樹中選擇一棵子樹,並保證子樹中含有節點1

- 把這棵子樹中的所有節點加上或減去1

你需要計算至少需要多少次操作來讓所有的節點的權值歸零。 輸入資料

第一行包含乙個整數n,表示樹中節點的數量

接下來的n-1行,一行兩個整數u,v,表示u和v之間有一條邊(u!=v)。

最後一行包含n個整數v_ivi​,用空格隔開,表示每個節點的權值 輸出資料

一行乙個整數,輸出最小需要的操作次數。 輸入樣例

3

1 21 3

1 -1 1

輸出樣例

3
資料規模 對於30\%30%的資料,n\leq100,|vi|\leq1000n≤100,∣vi∣≤1000

對於50\%50%的資料,n\leq10^4n≤104

對於100\%100%的資料,n\leq10^5,|vi|\leq10^9n≤105,∣vi∣≤109

translated by 首相大大

輸入 #1複製

3

1 21 3

1 -1 1

輸出 #1複製

3
題意:每次選的時候一定要包含1,但是子樹的大小不定,具體意思就是說選擇了乙個點,從這個點往上直到根節點1的經過的點都要同時加1/-1;

考慮樹形dp,add[x]:x點增加的次數,del[x]:x點減少的次數。

對於父節點,遍歷其兒子得出add[x]=max(add[x],add[v]),del[x]=max(del[x],del[v]);

原因在於,比如葉子節點a是7,葉子節點b是5,那麼更新的時候,開始葉子節點a和葉子節點b同時更新-1,到了葉子節點b為0了,就單單更新葉子節點a。這樣就是說其a和b的父親節點更新最大的7就可以。那麼-7和-5同理。

當葉子節點a是7,b是-5,那麼兩個點開始同時更新+1或者-1肯定不是最小,對b以及路上的+5,對a以及路上的-7,這樣其a和b的父親節點最終的更新值a[x]+=(add[x]-del[x]),也就是a[x]-=2,然後此時a和b葉子節點都為1,此時父親節點重複同樣的事情。樹形dp即可。

#include#include#include#include#include#include#include#include#include#define debug(a) cout<<#a<<"="void dfs(ll u,ll fa)

else

}int main(void)

for(ll i=1;i<=n;i++) cin>>a[i];

dfs(1,0);

cout

}

樹形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...

HLOJ 樹形DP前置 DFS(樹形DP入門)

給定一棵 n nn 個點的樹,根為 t tt求每個點的父親是哪個點,t tt 的父親輸出 0 00第一行兩個整數 n,t n,tn,t接下來 n 1 n 1n 1 行,每行兩個整數 x,y x,yx,y,表示 x,y x,yx,y 之間有一條邊 n nn 行,第 i ii 行乙個整數,表示 i ii...

樹形dp小結

這些天做了一些樹形dp的題目,感覺有了些領悟,尤其是理解到樹形揹包就是分組揹包之後。選出幾道不錯的總結一下 hdu 1520 hdu 4003 poj 1155 poj 2486 hdu 4313 hdu 4340 hdu 1520 入門水題 每個節點有權值,子節點和父節點不能同時選,問最後能選的最...