[luogu4107]兔子和樱花
有两个贪心:1.自底向上dfs,能删就删,这样显然是正确的,因为它最多只会造成它父亲不能删除;2.对于一个节点,优先删除其代价($c[i]+son[i]$)最大的i删除,一定最优,证明略
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 2000005 4 vector<int>v[N]; 5 int n,m,x,ans,a[N],son[N]; 6 bool cmp(int x,int y){ 7 return a[x]+son[x]<a[y]+son[y]; 8 } 9 void dfs(int k){ 10 for(int i=0;i<v[k].size();i++)dfs(v[k][i]); 11 sort(v[k].begin(),v[k].end(),cmp); 12 for(int i=0;i<v[k].size();i++){ 13 x=v[k][i]; 14 if (m<a[k]+a[x]+son[k]+son[x]-1)break; 15 ans++; 16 a[k]+=a[x]; 17 son[k]+=son[x]-1; 18 } 19 } 20 int main(){ 21 scanf("%d%d",&n,&m); 22 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 23 for(int i=1;i<=n;i++){ 24 scanf("%d",&son[i]); 25 for(int j=1;j<=son[i];j++){ 26 scanf("%d",&x); 27 v[i].push_back(x+1); 28 } 29 } 30 dfs(1); 31 printf("%d",ans); 32 }