NC13249 黑白樹 樹上貪心

2022-01-12 15:45:48 字數 1635 閱讀 1058

一棵n個點的有根樹,1號點為根,相鄰的兩個節點之間的距離為1。樹上每個節點i對應乙個值k[i]。每個點都有乙個顏色,初始的時候所有點都是白色的。

你需要通過一系列操作使得最終每個點變成黑色。每次操作需要選擇乙個節點i,i必須是白色的,然後i到根的鏈上(包括節點i與根)所有與節點i距離小於k[i]的點都會變黑,已經是黑的點保持為黑。問最少使用幾次操作能把整棵樹變黑。

第一行乙個整數n (1 ≤ n ≤ 10^5)

接下來n-1行,每行乙個整數,依次為2號點到n號點父親的編號。

最後一行n個整數為k[i] (1 ≤ k[i] ≤ 10^5)

樣例解釋:

對節點3操作,導致節點2與節點3變黑

對節點4操作,導致節點4變黑

對節點1操作,導致節點1變黑

乙個數表示最少操作次數
示例1

複製

412

11 2 2 1

複製

3
總算遇到樹上貪心的題了,雖然有點像dp

思路:看到樹的題,第一想法往往就是先考慮dfs

往上塗色,葉子節點必須要塗,這一點無可非議。

父親可能不用操作,兒子會幫忙塗好。

為了盡量選擇少一些的點進行操作,應該從操作後往上塗色盡可能遠的角度考慮,貪心思想。

如果操作兒子v比操作父親u大得多,那就不要操作父親,因為父親能塗的,兒子都能包辦,還要操作父親幹嘛?

如果兒子能往上塗的距離 小於 父親,那也不一定要非要操作父親,例如這種情況

此時操作葉子節點3就行,不用再操作2。

但是選擇往上塗色盡可能遠這個貪心角度顯然是對的。

通過dfs維護染色的最遠距離,同時更新父親塗色的最遠距離。

當某乙個點,開始塗色的兒子不能塗到這裡,那就可能交給較近的兒子覆蓋或者自己親自塗,操作的節點數就要+1,這樣可以避免貪心選擇塗色距離遠的而忽略了樹的規模之類的問題。

#include#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ll long long

#define inf 0x3f3f3f3f

using

namespace

std;

vector

a[100086

];int f[100086

];int k[100086

];int cnt=0

,n;int dfs(int

u)

if(now<=0

)

k[ f[u] ] = max(k[ f[u] ],k[u]-1);///

不論操作誰開始塗,維護父親的最遠距離

return now-1;}

intmain()

for(int i=1;i<=n;i++)

scanf("%d

",&k[i]);

dfs(1);

printf(

"%d\n

",cnt);

return0;

}

Nowcoder13249 黑白樹(樹形DP)

一棵n個點的有根樹,1號點為根,相鄰的兩個節點之間的距離為1。樹上每個節點i對應乙個值k i 每個點都有乙個顏色,初始的時候所有點都是白色的。你需要通過一系列操作使得最終每個點變成黑色。每次操作需要選擇乙個節點i,i必須是白色的,然後i到根的鏈上 包括節點i與根 所有與節點i距離小於k i 的點都會...

黑白樹 樹形 貪心

題目描述 一棵n個點的有根樹,1號點為根,相鄰的兩個節點之間的距離為1。樹上每個節點i對應乙個值k i 每個點都有乙個顏色,初始的時候所有點都是白色的。你需要通過一系列操作使得最終每個點變成黑色。每次操作需要選擇乙個節點i,i必須是白色的,然後i到根的鏈上 包括節點i與根 所有與節點i距離小於k i...

黑白樹(DFS 貪心)

題目傳送門 一棵n個點的有根樹,1號點為根,相鄰的兩個節點之間的距離為1。樹上每個節點i對應乙個值k i 每個點都有乙個顏色,初始的時候所有點都是白色的。你需要通過一系列操作使得最終每個點變成黑色。每次操作需要選擇乙個節點i,i必須是白色的,然後i到根的鏈上 包括節點i與根 所有與節點i距離小於k ...