【Bzoj4027】兔子与樱花

来源:互联网 发布:协同过滤算法流程图 编辑:程序博客网 时间:2024/06/09 23:02

题意

给一个n个结点的树,每个结点有最大载重m,上面有c[i]朵花,对于每个结点,它的儿子个数和花的朵数不能超过m。现在可以删掉一些结点,每删掉一个,它的花就会给父亲,求最多能删掉多少结点。


解析

树形Dp+贪心。
可以直接Dfs递归实现。
显然从权值小的开始删起。


#include <cstdio>#include <vector>#include <algorithm>#define Rep( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i<=(i##_END);i++)#define For( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i++)#define Lop( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i>=(i##_END);i--)#define Dnt( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i--)using std :: min;using std :: max;const int maxx = 2000000 + 25;int c[maxx];std :: vector <int> G[maxx];int n,m,x,y,z,ans;bool cmp(int a,int b) {return c[a] < c[b];}void Dfs(int x){    For( i , 0 , G[x].size() ) Dfs(G[x][i]);    std :: sort(G[x].begin(),G[x].end(),cmp);    c[x] += G[x].size();    For( i , 0 , G[x].size() ){        int now = c[G[x][i]];        if(c[x] + now - 1 <= m){            c[x] += now - 1;            ans ++;        }        else break;    }}int main(){    scanf("%d%d",&n,&m);    For( i , 0 , n ) scanf("%d",&c[i]);    For( i , 0 , n ){        scanf("%d",&x);        while( x-- ){            scanf("%d",&y);            G[i].push_back(y);        }    }    Dfs(0);    printf("%d",ans);    return 0;}
原创粉丝点击