zoukankan      html  css  js  c++  java
  • 【BZOJ】【4027】【HEOI2015】兔子与樱花

    贪心


      树上贪心问题……跟APIO2015练习赛的C很像啊……

      我的思路是:从叶子向上考虑,令a[x]表示x这个节点上樱花数量与儿子个数的和(即对于任意的x,都有$a[x]leq m$)每次从儿子的a值中贪心地选最小的加到当前节点中(当然还要-1),然后就不用管了……因为如果某个儿子不能删去,将后代并入父亲,那么之后也不可能在将父亲删去后,再将这个儿子删去,因为越向上樱花累积的越多,而且这样删过以后儿子也是会加上去的……呃总之就是有这么个性质吧。。。描述的不是很清楚请见谅。

      所以就可以贪心了……(感觉什么也没说)

      然而蒟蒻用的是vector……然后时空复杂度高的飞起……QAQ求老司机教正确姿势

     1 /**************************************************************
     2     Problem: 4027
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:5096 ms
     7     Memory:105224 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 4027
    11 #include<vector>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 #define pb push_back
    21 using namespace std;
    22 typedef long long LL;
    23 inline int getint(){
    24     int r=1,v=0; char ch=getchar();
    25     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
    26     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
    27     return r*v;
    28 }
    29 const int N=2000010;
    30 /*******************template********************/
    31 int n,m,c[N],a[N],ans;
    32 vector<int>G[N],V[N];
    33 void dfs(int x){
    34     a[x]=c[x];
    35     rep(i,G[x].size()){
    36         dfs(G[x][i]);
    37         a[x]++;
    38         V[x].pb(a[G[x][i]]);
    39     }
    40     if (V[x].size()) sort(V[x].begin(),V[x].end());
    41     rep(i,V[x].size()){
    42         if (a[x]+V[x][i]-1>m) break;
    43         a[x]=a[x]+V[x][i]-1;
    44         ans++;
    45     }
    46 }
    47 int main(){
    48 #ifndef ONLINE_JUDGE
    49     freopen("4027.in","r",stdin);
    50     freopen("4027.out","w",stdout);
    51 #endif
    52     n=getint(); m=getint();
    53     rep(i,n) c[i]=getint();
    54     rep(i,n){
    55         int x=getint();
    56         F(j,1,x){
    57             int y=getint();
    58             G[i].pb(y);
    59         }
    60     }
    61     dfs(0);
    62     printf("%d
    ",ans);
    63     return 0;
    64 }
    View Code

    4027: [HEOI2015]兔子与樱花

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 215  Solved: 124
    [Submit][Status][Discuss]

    Description

    很 久很久之前,森林里住着一群兔子。有一天,兔子们突然决定要去看樱花。兔子们所在森林里的樱花树很特殊。樱花树由n个树枝分叉点组成,编号从0到n-1, 这n个分叉点由n-1个树枝连接,我们可以把它看成一个有根树结构,其中0号节点是根节点。这个树的每个节点上都会有一些樱花,其中第i个节点有c_i朵 樱花。樱花树的每一个节点都有最大的载重m,对于每一个节点i,它的儿子节点的个数和i节点上樱花个数之和不能超过m,即son(i) + c_i <= m,其中son(i)表示i的儿子的个数,如果i为叶子节点,则son(i) = 0

    现在兔子们觉得樱花树上节点太多,希望去掉一些节点。当一个节点被去掉之后,这个节点上的樱花和它的儿子节点都被连到删掉节点的父节点上。如果父节点也被删除,那么就会继续向上连接,直到第一个没有被删除的节点为止。
    现在兔子们希望计算在不违背最大载重的情况下,最多能删除多少节点。
    注意根节点不能被删除,被删除的节点不被计入载重。

    Input

    第一行输入两个正整数,n和m分别表示节点个数和最大载重

    第二行n个整数c_i,表示第i个节点上的樱花个数
    接下来n行,每行第一个数k_i表示这个节点的儿子个数,接下来k_i个整数表示这个节点儿子的编号

    Output

     一行一个整数,表示最多能删除多少节点。

    Sample Input

    10 4
    0 2 2 2 4 1 0 4 1 1
    3 6 2 3
    1 9
    1 8
    1 1
    0
    0
    2 7 4
    0
    1 5
    0

    Sample Output

    4

    HINT

    对于100%的数据,1 <= n <= 2000000, 1 <= m <= 100000, 0 <= c_i <= 1000


    数据保证初始时,每个节点樱花数与儿子节点个数之和大于0且不超过m

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    BZOJ 3132: 上帝造题的七分钟 树状数组+差分
    PAT Advanced 1006 Sign In and Sign Out (25 分)
    PAT Advanced 1011 World Cup Betting (20 分)
    PAT Basic 1032 挖掘机技术哪家强 (20 分)
    PAT Basic 1028 人口普查 (20 分)
    PAT Basic 1004 成绩排名 (20 分)
    大数据数据库HBase(二)——搭建与JavaAPI
    PAT Advanced 1009 Product of Polynomials (25 分)(vector删除元素用的是erase)
    PAT Advanced 1002 A+B for Polynomials (25 分)(隐藏条件,多项式的系数不能为0)
    PAT Basic 1041 考试座位号 (15 分)
  • 原文地址:https://www.cnblogs.com/Tunix/p/4498059.html
Copyright © 2011-2022 走看看