BZOJ4027 HEOI2015兔子与樱花(贪心)

  首先显然地如果某个点超过了最大负载,删掉它仍然是不合法的。删除某个点当前只会对其父亲产生影响,同一个节点的儿子显然应该按代价从小到大删。考虑如果删掉某个点之后他的父亲不能再删了,我们损失了父亲这个点,但不会对其他点产生任何影响;而若删掉父亲,其儿子节点中能够删除的节点肯定会更少,且会对爷爷造成负面影响。所以我们贪心的自底向下删点就好了。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 2000010
int n,m,a[N],s[N],t,ans;
vector<int> son[N];
bool cmp(const int&x,const int&y)
{
    return a[x]<a[y];
}
void dfs(int k) 
{
    int cnt=0;
    for (int i=0;i<s[k];i++) dfs(son[k][i]);
    sort(son[k].begin(),son[k].end(),cmp);
    for (int i=0;i<s[k];i++)
    if (a[k]+a[son[k][i]]-1<=m) a[k]+=a[son[k][i]]-1,ans++;
    else break;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj4027.in","r",stdin);
    freopen("bzoj4027.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read(),m=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<=n;i++)
    {
        a[i]+=s[i]=read();
        for (int j=1;j<=s[i];j++) son[i].push_back(read()+1);
    }
    dfs(1);
    cout<<ans;
    return 0;
}

 

posted @ 2018-10-21 13:54  Gloid  阅读(169)  评论(0编辑  收藏  举报