BZOJ 4027: [HEOI2015]兔子与樱花【树形DP】【贪心】

对于每一个删点操作,我们考虑当前节点的樱花数量。

由于我们要尽可能地多删点,所以我们要尽量删除樱花数少的点。

对于每一个节点,我们将它的儿子节点按照樱花数量从小到大排序,优先选择樱花数量更小的那个节点,判断是否符合条件,如果是,则删除。

#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define db double
#define sg string
#define ll long long
#define rel(i,x,y) for(ll i=(x);i<(y);i++)
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define red(i,x,y) for(ll i=(x);i>=(y);i--)
#define res(i,x) for(ll i=head[x];i;i=nxt[i])
using namespace std;

const ll N=2e6+5;
const ll Inf=1e18;
const db Eps=1e-10;

ll n,m,tot,c[N];

vector<ll>ed[N];

inline ll read() {
	ll x=0;char ch=getchar();bool f=0;
	while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return f?-x:x;
}

bool cmp(ll p,ll q) {
	return c[p]<c[q];
}

void dfs(ll x) {
	rel(i,0,ed[x].size()) dfs(ed[x][i]);
	
	sort(ed[x].begin(),ed[x].end(),cmp);

	c[x]+=ed[x].size();
	
	rel(i,0,ed[x].size()) {
		ll ret=c[ed[x][i]];
		
		if(c[x]+ret-1<=m) {
			tot++;c[x]+=ret-1;
		} else break;
	}
}

int main() {
	n=read(),m=read();
	
	rep(i,1,n) c[i]=read();
	
	rep(i,1,n) {
		ll cnt=read();
		while(cnt--) {
			ll j=read()+1;
			ed[i].push_back(j);
		}
	}
	
	dfs(1);
	
	printf("%lld\n",tot);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/83476855