BZOJ4027 兔子與櫻花

2022-03-27 03:10:27 字數 1587 閱讀 1145

time limit: 10 sec  memory limit: 256 mb

很久很久之前,森林裡住著一群兔子。有一天,兔子們突然決定要去看櫻花。兔子們所在森林裡的櫻花樹很特殊。櫻花樹由n個樹枝分叉點組成,編號從0到n-1,這n個分叉點由n-1個樹枝連線,我們可以把它看成乙個有根樹結構,其中0號節點是根節點。這個樹的每個節點上都會有一些櫻花,其中第i個節點有c_i朵櫻花。櫻花樹的每乙個節點都有最大的載重m,對於每乙個節點i,它的兒子節點的個數和i節點上櫻花個數之和不能超過m,即son(i) + c_i <= m,其中son(i)表示i的兒子的個數,如果i為葉子節點,則son(i) = 0

現在兔子們覺得櫻花樹上節點太多,希望去掉一些節點。當乙個節點被去掉之後,這個節點上的櫻花和它的兒子節點都被連到刪掉節點的父節點上。如果父節點也被刪除,那麼就會繼續向上連線,直到第乙個沒有被刪除的節點為止。

現在兔子們希望計算在不違背最大載重的情況下,最多能刪除多少節點。

注意根節點不能被刪除,被刪除的節點不被計入載重。

第一行輸入兩個正整數,n和m分別表示節點個數和最大載重

第二行n個整數c_i,表示第i個節點上的櫻花個數

接下來n行,每行第乙個數k_i表示這個節點的兒子個數,接下來k_i個整數表示這個節點兒子的編號

一行乙個整數,表示最多能刪除多少節點。

10 4

0 2 2 2 4 1 0 4 1 1

3 6 2 3

1 91 8

1 10

02 7 4

01 504

對於100%的資料,1 <= n <= 2000000, 1 <= m <= 100000, 0 <= c_i <= 1000

資料保證初始時,每個節點櫻花數與兒子節點個數之和大於0且不超過m

題解考試時看到這道題前10分鐘認為他是個樹歸

本著「我什麼動歸都不會啊」的心態打了個小暴力,然後就去看後面的題

竟然出乎意料的靠近正解,雖然差了最關鍵的一步排序2333

這個題我們可以這樣想(感性理解一下),如果我們不貪心求,無論用什麼詭異的方法計算,

最後肯定要把兒子合併到父親上去(其實是因為想不出來應該怎麼奇怪的合併)

那麼我們肯定是先合併權值較小的點,再合併權值較大的點得到的解最優

具體**實現可以用小根堆,也可以和我一樣用vector邪教排序,也可以搞其他奇怪的事情

**見下:

1 #include2 #include3 #include4 #include5

using

namespace

std;

6const

int n=2000100

;7 vectorson[n];

8int

n,m,cnt,c[n],ge[n];

9 inline bool mp(const

int &a,const

int &b)

10void dfs(int

rt)1121}

22int

main()

2333 dfs(0

);34 printf("%d"

,cnt);

35 }

bzoj4027

Bzoj4027 兔子與櫻花

給乙個n個結點的樹,每個結點有最大載重m,上面有c i 朵花,對於每個結點,它的兒子個數和花的朵數不能超過m。現在可以刪掉一些結點,每刪掉乙個,它的花就會給父親,求最多能刪掉多少結點。樹形dp 貪心。可以直接dfs遞迴實現。顯然從權值小的開始刪起。include include include de...

bzoj4027 兔子與櫻花

看來該去惡補一下貪心了 對於某乙個節點來說,可以發現從小到 擇它的兒子的cost是最優的 因為要選盡量多的節點 那麼就可以去遞迴搞了,然後排個序就行。1 include 2 include 3 include 4 include 5 include 6 include 7 include 8 inc...

BZOJ4027 兔子與櫻花(貪心)

bzoj 洛谷很直觀的乙個感受就是對於每個節點,考慮它的所有兒子,如果能刪就刪。那麼我們把所有兒子按照給刪去後給父親c i c i 的貢獻從小往大排序,能刪就刪即可。include include using namespace std define ll long long define max ...