[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 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/11629265.html