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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章