[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;
}