bzoj4027 [HEOI2015]兔子與櫻花 樹上貪心
阿新 • • 發佈:2017-12-26
while ans time 題解 back lin algo 情況 兔子
Submit: 1320 Solved: 762
[Submit][Status][Discuss]
現在兔子們覺得櫻花樹上節點太多,希望去掉一些節點。當一個節點被去掉之後,這個節點上的櫻花和它的兒子節點都被連到刪掉節點的父節點上。如果父節點也被刪除,那麽就會繼續向上連接,直到第一個沒有被刪除的節點為止。
現在兔子們希望計算在不違背最大載重的情況下,最多能刪除多少節點。
註意根節點不能被刪除,被刪除的節點不被計入載重。
0 2 2 2 4 1 0 4 1 1
3 6 2 3
1 9
1 8
1 1
0
0
2 7 4
0
1 5
0
數據保證初始時,每個節點櫻花數與兒子節點個數之和大於0且不超過m
[HEOI2015]兔子與櫻花
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1320 Solved: 762
[Submit][Status][Discuss]
Description
很久很久之前,森林裏住著一群兔子。有一天,兔子們突然決定要去看櫻花。兔子們所在森林裏的櫻花樹很特殊。櫻花樹由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
Input
第一行輸入兩個正整數,n和m分別表示節點個數和最大載重
第二行n個整數c_i,表示第i個節點上的櫻花個數 接下來n行,每行第一個數k_i表示這個節點的兒子個數,接下來k_i個整數表示這個節點兒子的編號Output
一行一個整數,表示最多能刪除多少節點。
Sample Input
10 40 2 2 2 4 1 0 4 1 1
3 6 2 3
1 9
1 8
1 1
0
0
2 7 4
0
1 5
0
Sample Output
4HINT
對於100%的數據,1 <= n <= 2000000, 1 <= m <= 100000, 0 <= c_i <= 1000
數據保證初始時,每個節點櫻花數與兒子節點個數之和大於0且不超過m
Source
題解:
樹形貪心。對於任意一個節點,它當前的權值為c[i]+son[i]。
假設我們刪除了它的某一個兒子節點j,則權值增加c[j]+son[j]-1。
那麽顯然,我們在刪除節點的時候,應該從權值最小的到最大的依次進行,直到當前節點的權值已經超過限重。
1 #include<cstring> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdio> 6 #include<vector> 7 8 #define N 2000007 9 #define ll long long 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(ch>‘9‘||ch<‘0‘){if (ch==‘-‘) f=-1;ch=getchar();} 15 while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();} 16 return x*f; 17 } 18 19 int n,m,ans; 20 int c[N]; 21 vector<int>e[N]; 22 23 bool cmp(int a,int b){return c[a]<c[b];} 24 void dfs(int x) 25 { 26 for(int i=0;i<e[x].size();i++) 27 dfs(e[x][i]); 28 sort(e[x].begin(),e[x].end(),cmp); 29 c[x]+=e[x].size(); 30 for(int i=0;i<e[x].size();i++) 31 { 32 int t=c[e[x][i]]; 33 if(c[x]+t-1<=m) 34 { 35 c[x]+=t-1; 36 ans++; 37 } 38 } 39 } 40 int main() 41 { 42 n=read();m=read(); 43 for(int i=0;i<n;i++) 44 c[i]=read(); 45 for(int i=0,x,y;i<n;i++) 46 { 47 x=read(); 48 while(x--) 49 { 50 y=read(); 51 e[i].push_back(y); 52 } 53 } 54 dfs(0),printf("%d\n",ans); 55 }
bzoj4027 [HEOI2015]兔子與櫻花 樹上貪心