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。
 
 
题解:
  树形动态规划+贪心。对于任意一个节点,它当前的权值为c[i]+son[i]。假设我们删除了它的某一个儿子节点j,则权值增加c[j]+son[j]-1。那么显然,我们在删除节点的时候,应该从权值最小的到最大的依次进行,直到当前节点的权值已经超过限重。
  其实这种思路应该是算不上动态规划的,最重要的还是贪心部分。全过程直接用DFS就可以完成。建议加读入优化,2*10^6的数据不是盖的。
 
代码:
----------------------------------------------------------------------------------------------------

#include <cstdio>
#include <algorithm>
#define MAXN 2000005
using namespace std;

struct Edge { int v, next; } edge[MAXN];

int w[MAXN], son[MAXN], n, m, now, h[MAXN], v, f[MAXN], st[MAXN];

int read()
{
  int res = 0; char ch = getchar();
  while (ch < '0' && ch > '9') ch = getchar();
  while (ch >= '0' && ch <= '9') res = res * 10 + ch - '0', ch = getchar();
  return res;
}

int DFS(int o)
{
  int cnt = 0;
  for (int x = h[o]; x; x = edge[x].next)
  {
    int v = edge[x].v;
    DFS(v), w[o]++, f[o] += f[v];
  }
  for (int x = h[o]; x; x = edge[x].next) st[++cnt] = w[edge[x].v];
  sort(st + 1, st + cnt + 1);
  for (int i = 1; i <= cnt; i++)
    if (w[o] + st[i] - 1 <= m) w[o] += st[i] - 1, f[o]++; else break;
  return f[o];
}

int main()
{
  freopen("4027.in", "r", stdin);
  freopen("4027.out", "w", stdout);
  n = read(), m = read();
  for (int i = 0; i <= n - 1; i++) w[i] = read();
  for (int i = 0; i <= n - 1; i++)
  {
    son[i] = read();
    for (int j = 1; j <= son[i]; j++) v = read(), now++, edge[now] = (Edge) {v, h[i]}, h[i] = now;
  }
  printf("%d", DFS(0));
  return 0;
}

----------------------------------------------------------------------------------------------------

[BZOJ4027][HEOI2015] 兔子与樱花的更多相关文章

  1. BZOJ4027: [HEOI2015]兔子与樱花 贪心

    觉得是贪心,但是一开始不太肯定...然后就A了 一个点对它的父亲的贡献就是自己的权值加儿子的个数 #include<bits/stdc++.h> using namespace std; ...

  2. bzoj4027 [HEOI2015]兔子与樱花 树上贪心

    [HEOI2015]兔子与樱花 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1320  Solved: 762[Submit][Status][Di ...

  3. [bzoj4027][HEOI2015]兔子与樱花_贪心_树形dp

    兔子与樱花 bzoj-4027 HEOI-2015 题目大意:每个点有c[i]朵樱花,有一个称重m, son[i]+c[i]<=m.如果删除一个节点,这个节点的樱花或移动到它的祖先中深度最大的, ...

  4. [BZOJ4027][HEOI2015]兔子与樱花 树形dp

    Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接 ...

  5. [bzoj4027][HEOI2015][兔子与樱花] (树形dp思想+玄学贪心)

    Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接 ...

  6. BZOJ4027 HEOI2015兔子与樱花(贪心)

    首先显然地如果某个点超过了最大负载,删掉它仍然是不合法的.删除某个点当前只会对其父亲产生影响,同一个节点的儿子显然应该按代价从小到大删.考虑如果删掉某个点之后他的父亲不能再删了,我们损失了父亲这个点, ...

  7. 【BZOJ4027】[HEOI2015]兔子与樱花 贪心

    [BZOJ4027][HEOI2015]兔子与樱花 Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组 ...

  8. B20J_4027_[HEOI2015]兔子与樱花_树形DP

    B20J_4027_[HEOI2015]兔子与樱花_树形DP 题意: 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编 ...

  9. 【BZOJ4027】兔子与樱花(贪心)

    [BZOJ4027]兔子与樱花(贪心) 题面 BZOJ 洛谷 题解 很直观的一个感受就是对于每个节点, 考虑它的所有儿子,如果能删就删. 那么我们把所有儿子按照给删去后给父亲\(c[i]\)的贡献从小 ...

随机推荐

  1. 深入理解javascript原型和闭包(11)——执行上下文栈

    继续上文的内容. 执行全局代码时,会产生一个执行上下文环境,每次调用函数都又会产生执行上下文环境.当函数调用完成时,这个上下文环境以及其中的数据都会被消除,再重新回到全局上下文环境.处于活动状态的执行 ...

  2. R中的<-和=赋值符号的细致区别

    <-创建的变量的作用范围可以在整个顶层环境,而=仅仅在一个局部环境. 但要<-创建的变量如果是在函数实参传递的时候创建的,其的作用范围可以在整个顶层环境,有一个前提条件:对应的形参在函数内 ...

  3. 升级到 PHP-7 遇到的坑 及 经验分享

    注意:上面这张图是QQ群网友分享的,图中提到的“被移除的函数”,call_user_func 和 call_user_func_array 在 PHP-7.0 的正式版中是可用的,也许是当时的 测试版 ...

  4. Windows环境配置HTTP服务(Windows + Apache + Mysql + PHP)

    1.安装WampServer 2.管理HTTP服务 任务图标绿色为正常启动状态 注意事项:1.检查网络是不是通的 ping 对方IP2.检查防火墙是否开启,如果开启将不能正常被访问3.检查访问权限 A ...

  5. UVA2037

    #include<cstdio> int Sum(int n) { int sum=0; while(n!=0) { sum+=n%10; n/=10; } return sum; } v ...

  6. StartUML反向(逆向)Java工程通过代码生成类图

     在软件工程中,通过都是先了详细设计,然后按照详细设计来进行开发.在编写详细设计的时候,通常都会画一些类图.时序图.流程图等等UML设计,然后通过uml类图生成代码,这个属于正向工程生成代码,然而在实 ...

  7. C# 文件/文件夹重命名

    C# 重命名的方法是MoveTo() 官方文档地址 (https://msdn.microsoft.com/zh-cn/library/system.io.fileinfo.moveto%28VS.8 ...

  8. spring aop 环绕通知around和其他通知的区别

    前言: spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别: 1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知   是不能决定的,他们只 ...

  9. linux升级openssl

    wget https://www.openssl.org/source/openssl-1.0.2j.tar.gz ./config shared zlib-dynamicconfig完成后执行 ma ...

  10. MyEclipse 10, 2013, 2014 破解、注册码

    MyEclipse 试用期限一般是三十天,过了三十天后 MyEclipse 会提示用户注册而不能正常使用,这里分享一下破解过程,仅供学习和参考. MyEclipse 10, 2013, 2014 破解 ...