当前位置: 首页 > news >正文

4027. [HEOI2015]兔子与樱花【树形DP】

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
 
说是树形DP,其实本质还算贪心……
很容易发现,每个点删掉后对父亲的贡献为Son[x]+a[x]-1
而你删除点x,最多会对Father[x]产生影响,再往上的节点很容易发现就不会受到影响了
(画个图感性体会一下什么都好说)
所以对于点x来说,按儿子Cost从小到大删除
因为如果你不删除儿子的话,最好的情况就是可以在下一步删除x
那样还不如删除儿子,反正儿子要删除的话至少会删除一个
当然如果所有儿子都没法删除那就没办法了QvQ
 
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #define N (2000000+100)
 6 using namespace std;
 7 struct node
 8 {
 9     int to,next;
10 }edge[N*2];
11 int a[N],b[N],Son[N],Father[N],Cost[N];
12 int head[N],num_edge,n,m,p,ans,x;
13 
14 void add(int u,int v)
15 {
16     edge[++num_edge].next=head[u];
17     edge[num_edge].to=v;
18     head[u]=num_edge;
19 } 
20 
21 void Build(int x)
22 {
23     for (int i=head[x];i!=0;i=edge[i].next)
24         if (edge[i].to!=Father[x])
25         {
26             Father[edge[i].to]=x;
27             Son[x]++;
28             Build(edge[i].to);
29         }
30     Cost[x]=Son[x]+a[x];
31 }
32 
33 void Dfs(int x)
34 {
35     for (int i=head[x];i!=0;i=edge[i].next)
36         if (edge[i].to!=Father[x])
37             Dfs(edge[i].to);
38     int cnt=0;
39     for (int i=head[x];i!=0;i=edge[i].next)
40         if (edge[i].to!=Father[x])
41             b[++cnt]=Cost[edge[i].to]-1;
42     sort(b+1,b+cnt+1);
43     for (int i=1;i<=cnt;++i)
44         if (Cost[x]+b[i]<=m)
45             Cost[x]+=b[i],ans++; 
46 }
47 
48 int main()
49 {
50     scanf("%d%d",&n,&m);
51     for (int i=1;i<=n;++i)
52         scanf("%d",&a[i]);
53     for (int i=1;i<=n;++i)
54     {
55         scanf("%d",&p);
56         for (int j=1;j<=p;++j)
57         {
58             scanf("%d",&x); x++;
59             add(x,i); add(i,x);
60         }
61     }
62     Build(1);
63     Dfs(1);
64     printf("%d",ans);
65 }

转载于:https://www.cnblogs.com/refun/p/8680806.html

相关文章:

  • 1491. [NOI2007]社交网络【最短路计数】
  • Java基础-比较运算符Compare Operators
  • LDAP DIT设计参考
  • 爬取校园新闻首页的新闻
  • 学习索引结构的一些案例——Jeff Dean在SystemML会议上发布的论文
  • node爬虫-使用puppeteer
  • 使用linux下的crontab定时任务跑定时脚本
  • mycat的wrapper.log日志中发现主从切换报错
  • react组件的生命周期
  • oracle中两个时间类型的数据相减默认得到的是天数。
  • 阿里云禁止25端口,使用465端口发送运维邮件
  • CentOS下设置Tomcat开机自动启动操作步骤
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • 柔弱的APP如何自我保护,浅谈APP防御手段,使用360加固助手加固/签名/多渠道打包/应用市场发布...
  • vue-学习系列之vue双向绑定原理
  • [译] 怎样写一个基础的编译器
  • Angular数据绑定机制
  • css属性的继承、初识值、计算值、当前值、应用值
  • ES10 特性的完整指南
  • gf框架之分页模块(五) - 自定义分页
  • IDEA常用插件整理
  • JavaScript DOM 10 - 滚动
  • JavaScript 奇技淫巧
  • Mybatis初体验
  • Python十分钟制作属于你自己的个性logo
  • unity如何实现一个固定宽度的orthagraphic相机
  • Vue官网教程学习过程中值得记录的一些事情
  • 高性能JavaScript阅读简记(三)
  • 诡异!React stopPropagation失灵
  • 前端面试之闭包
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 使用API自动生成工具优化前端工作流
  • 正则与JS中的正则
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #HarmonyOS:软件安装window和mac预览Hello World
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (1)bark-ml
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (30)数组元素和与数字和的绝对差
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)VC++中ondraw在什么时候调用的
  • (转)程序员技术练级攻略
  • (转)德国人的记事本
  • (转)拼包函数及网络封包的异常处理(含代码)
  • (转)平衡树
  • (转)重识new
  • .bat批处理(三):变量声明、设置、拼接、截取