[HEOI2015]兔子与樱花

[HEOI2015]兔子与樱花

题目大意:

一棵\(n(n\le2\times10^6)\)个点的树,每个点有一个重量\(c_i\)和一个载重上限\(m\)。删除一个结点时,将自身的重量加到父结点上,并将所有子结点连到父结点上。问若要保证对于任意一个结点,子结点数与重量之和\(\le m\)时,最多删去几个结点。

思路:

自底向上贪心,子结点按照\(c_i\)排序,能删除的尽量删除。

时间复杂度\(\mathcal O(n\log n)\)

源代码:

#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
const int N=2e6+1;
int n,m,c[N],cnt[N],ans;
std::vector<int> e[N];
inline void add_edge(const int &u,const int &v) {
	e[u].push_back(v);
}
inline bool cmp(const int &i,const int &j) {
	return c[i]<c[j];
}
void dfs(const int &x) {
	for(unsigned i=0;i<e[x].size();i++) {
		const int &y=e[x][i];
		dfs(y);
	}
	std::sort(e[x].begin(),e[x].end(),cmp);
	for(unsigned i=0;i<e[x].size();i++) {
		const int &y=e[x][i];
		if(c[x]+cnt[x]+c[y]+cnt[y]-1<=m) {
			c[x]+=c[y];
			cnt[x]+=cnt[y]-1;
			ans++;
		}
	}
}
int main() {
	n=getint(),m=getint();
	for(register int i=0;i<n;i++) c[i]=getint();
	for(register int i=0;i<n;i++) {
		for(register int k=cnt[i]=getint();k;k--) {
			add_edge(i,getint());
		}
	}
	dfs(0);
	printf("%d\n",ans);
	return 0;
}
posted @ 2018-10-25 10:14  skylee03  阅读(245)  评论(0编辑  收藏  举报