题意
有一棵树,里面有很多点,每个点上有一个樱花量 a [ i ] a[i] a[i] ,然后他的儿子数为 s o n [ i ] son[i] son[i] ,删除点以后这个点的樱花和儿子都会继承给他的父亲,问最多删除多少点,能满足删除的点的父亲满足 a [ i ] + s o n [ i ] ≤ m a[i]+son[i]\leq m a[i]+son[i]≤m,输出最多删除的点数
解题方法
我们很容易就会想到从下向上来解决本到题,然后我们就贪心的想,我们想删的点一定是对上面父亲的值增加最小的,那么我们就用一个新的数组 k e y [ i ] key[i] key[i] 来存 a [ i ] + s o n [ i ] a[i]+son[i] a[i]+son[i] ,然后我们对于一个点来说我们就按照这个从小到大排序一遍,然后看是否能删,能删就删,然后统计答案就可以了/
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int key[4000010],a[4000010],sonsum[4000010];
int l[4000010],r[4000010],son[4000010];
int ans=0;
int n,m;
bool comp(int x,int y)
{
return key[x]<key[y];
}
void dfs(int now)
{
if(!sonsum[now])return;
for(int i=l[now];i<=r[now];i++)
dfs(son[i]);
sort(son+l[now],son+r[now]+1,comp);
for(int i=l[now];i<=r[now];i++)
if(key[son[i]]+key[now]-1<=m)
{
ans++;
key[now]+=key[son[i]]-1;
}
return;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int now=0;
for(int i=0;i<n;i++)
{
scanf("%d",&sonsum[i]);
key[i]=sonsum[i]+a[i];
if(!sonsum[i])continue;
l[i]=now+1;
r[i]=now+sonsum[i];
now=r[i];
for(int j=l[i];j<=r[i];j++)
scanf("%d",&son[j]);
}
dfs(0);
cout<<ans<<'\n';
}