題目描述
一棵樹是乙個有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複製1 21 3
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 入門水題 每個節點有權值,子節點和父節點不能同時選,問最後能選的最...