题目描述:
给出一棵树
一个点的载重定义为 Ri+Son(i)
若删去一个点 那么这个点的载重会加到本点存在的祖先节点
给出一个载重限制 m
问在每个节点载重都不超出 m的情况下 最多删去几个节点
不能删去根节点
题目分析:
最水的省选题目了
我们贪心着搞就行了,先删去载重最小的儿子
节点标号是从0-N-1
题目链接:
BZOJ 4027
COGS 1968
Luogu 4107
Ac 代码:
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
const int maxm=2100000;
int n,m,ans;
int nowm[maxm];
std::vector <int> v[maxm];
inline bool comp(int x,int y)
{
return nowm[x]<nowm[y];
}
void dfs(int now)
{
//printf("%d %d\n",now,nowm[now]);
for(int i=0;i<v[now].size();i++) dfs(v[now][i]);
std::sort(v[now].begin(),v[now].end(),comp);
for(int i=0;i<v[now].size();i++)
{
int tmp=v[now][i];
//printf("%d %d\n",now,tmp);
if(nowm[tmp]+nowm[now]-1<=m) nowm[now]=nowm[now]+nowm[tmp]-1,ans++;
else break;
}
//printf("%d %d\n",now,nowm[now]);
}
int main()
{
//freopen("sakura.in","r",stdin);
//freopen("sakura.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&nowm[i]);
for(int i=1;i<=n;i++)
{
int sonnum;
scanf("%d",&sonnum);
nowm[i]+=sonnum;
for(int j=1,x;j<=sonnum;j++)
scanf("%d",&x),x++,v[i].push_back(x);
}
dfs(1);
printf("%d",ans);
return 0;
}