BZOJ 4027 [HEOI2015]兔子与樱花 - 贪心

可能做了假题。。。一开始想二维树形dp,结果发现nm乘起来肯定会挂,然后继续膜hzwer学长的代码,发现是道瓜题。。。

考虑这样一个结论,下面删点肯定不上面删点优:
如果一个节点x其子节点可以被删去,那么至少可以删去一个点,贡献至少为1,而对于x的父节点毫无影响;而若删去x节点,从对答案的贡献上来讲也是1,不会更优,而会让父节点的剩余空间更小,一定不如删去x子节点优。
由是从下向上贪心,每次将子节点排序,选择删去代价最小的子节点,总复杂度为O(nlogn)

(贪心策略在考场上根本想不到好吗。。。)

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<algorithm>

using namespace std;

const int maxn=2000005;

int n,m,ans;
int c[maxn];

vector<int>son[maxn];

bool cmp(int a,int b)
{
    return c[a]<c[b];
}
void dfs(int x)
{
    int sz=son[x].size();
    for(int i=0;i<sz;i++)
        dfs(son[x][i]);
    sort(son[x].begin(),son[x].end(),cmp);
    for(int i=0;i<sz;i++)
    {
        if(c[x]+c[son[x][i]]-1<=m)
        {
            c[x]+=c[son[x][i]]-1;
            ans++;
        }
        else break;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0,tmp;i<n;i++)
        scanf("%d",c+i);
    for(int i=0,tmp,temp;i<n;i++)
    {
        scanf("%d",&tmp);
        c[i]+=tmp;
        while(tmp--)
        {
            scanf("%d",&temp);
            son[i].push_back(temp);
        }
    }
    dfs(0);
    cout<<ans;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章