P4629 SHOI2015 聚变反应炉
P4629 SHOI2015 聚变反应炉
树上背包+树形dp。
算是套娃题吗?
思路
看到数据考虑数据分治。
part1 贪心 \(c_i\leq 1\)
对于这种情况,我们考虑贪心的点亮。
手玩几组数据,发现只要先全部点亮 \(c_i=1\) 的点,都可以得到最优解。
若存在一个 \(c_i=1\) 的节点连接 \(1\) 的节点个数小于 \(d_i\),设个数为 \(w\),那么我们后选他可以减少 \(w\) 的能量。
若我们在中途的某一个时刻选择这个点,他也可以对答案减少 \(w\) 的能量(\(d_i\geq 1\),没激活的邻接点 \(-1\),激活的也可以 \(-1\))。
若这个点的 \(d_i\) 小于连接 \(1\) 的节点的个数,若我们需要花费能量激活的话,和上述情况同理;若不需要花费能量激活,此时的没有被激活的边又可以造成 \(-1\) 的贡献。
所以无论选择的顺序,只要先选择 \(c=1\) 的点,我们一定可以最小化答案。
至于等于 \(c=0\) 的点,吸收完所有 \(c=1\) 的点的贡献在激活一定是最优的。
part2 树形 dp
首先这题的状态不是很好设,因为要考虑儿子的贡献,父亲的贡献,很容易就混进去了。
我们不妨想着先解决父亲的贡献。
设 \(dp[u][0]\) 为 \(u\) 先点亮,且 \(u\) 子树内均被点亮的最小能量,\(dp[u][1]\) 为 \(u\) 的父亲比 \(u\) 先被点亮,\(u\) 的子树内再被点亮的最小能量。
显然这样子没有考虑儿子的传递的能量,我们是写不出转移方程的。
不如设 \(tmp[u][i][j]\) 为 \(u\) 的前 \(i\) 个儿子给 \(u\) 传递了 \(j\) 的能量,点亮前 \(i\) 个儿子的子树内的所有点的最小能量。
这里有转移:
tmp[u][i][j]=\min(dp[u][i][j],tmp[u][i-1][j]+dp[v][1])
\]
不难发现我们这是一个树上背包,我们对其使用滚动数组优化。
tmp[u][cur][j]=\min(dp[u][cur][j],tmp[u][cur\oplus 1][j]+dp[v][1])
\]
对于 \(dp[u][0/1]\) 有转移:
令 \(sum=\sum_{v\in u.sons} c[v]\),\(fa\) 为 \(u\) 的父亲。
dp[u][1]=\min_{i=0}^{sum}(dp[u][0],\max(tmp[i],tmp[i]-i+d[u]-c[fa]))
\]
由于父亲的方程和 \(tmp\) 无关,可以每次新开一个 \(tmp\) 数组。
最后 \(dp[1][0]\) 就是答案喽。
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e5+5,maxm=3e3+5;
struct Edge
{
int tot;
int head[maxn];
struct edgenode{int to,nxt;}edge[maxn*2];
inline void add(int x,int y)
{
tot++;
edge[tot].to=y;
edge[tot].nxt=head[x];
head[x]=tot;
}
}T;
int n;
int d[maxn],c[maxn];
ll dp[maxm][2],tmp[2][maxm*5];
inline void solve()
{
ll ans=0;
for(int i=1;i<=n;i++)
{
if(c[i]==1)
{
ans+=d[i];d[i]=0;
for(int j=T.head[i];j;j=T.edge[j].nxt)
{
int v=T.edge[j].to;
d[v]--;
}
}
}
for(int i=1;i<=n;i++) if(d[i]>0) ans+=d[i];
printf("%lld",ans);
}
inline void dfs(int u,int f)//dp 部分
{
int sum=0;
for(int i=T.head[u];i;i=T.edge[i].nxt)
{
int v=T.edge[i].to;
if(v==f) continue;
dfs(v,u);sum+=c[v];
}
memset(tmp,0x3f,sizeof(tmp));
tmp[0][0]=0;
int cur=0;
for(int i=T.head[u];i;i=T.edge[i].nxt)
{
int v=T.edge[i].to;
if(v==f) continue;
cur^=1;
memset(tmp[cur],0x3f,sizeof(tmp[cur]));
for(int j=0;j<=sum-c[v];j++)
{
tmp[cur][j+c[v]]=min(tmp[cur][j+c[v]],tmp[cur^1][j]+dp[v][0]);
tmp[cur][j]=min(tmp[cur][j],tmp[cur^1][j]+dp[v][1]);
}
}
for(int i=0;i<=sum;i++)
{
dp[u][0]=min(dp[u][0],max(tmp[cur][i],tmp[cur][i]-i+d[u]));
dp[u][1]=min(dp[u][1],max(tmp[cur][i],tmp[cur][i]-i+d[u]-c[f]));
}
}
int main()
{
int mx=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&d[i]);
for(int i=1;i<=n;i++) scanf("%d",&c[i]),mx=max(c[i],mx);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
T.add(x,y),T.add(y,x);
}
if(mx<=1) solve(),exit(0);
memset(dp,0x3f,sizeof(dp));
dfs(1,0);
printf("%lld",dp[1][0]);
}
P4629 SHOI2015 聚变反应炉的更多相关文章
- 洛谷 P4269 / loj 2041 [SHOI2015] 聚变反应炉 题解【贪心】【DP】
树上游戏..二合一? 题目描述 曾经发明了零件组装机的发明家 SHTSC 又公开了他的新发明:聚变反应炉--一种可以产生大量清洁能量的神秘装置. 众所周知,利用核聚变产生的能量有两个难点:一是控制核聚 ...
- [SHOI2015]聚变反应炉[树dp、贪心]
题意 给定一棵 \(n\) 个点的树,每个点有一个启动能量 \(d\) 和传递能量 \(c\) ,如果一个点被启动了,就会向和他直接相连的点发送 \(c\) 的能量,初始所有节点能量为0,问最少多少能 ...
- bzoj4593: [Shoi2015]聚变反应炉
这道题的难点其实是在设DP方程,见过就应该会了 令f0,i表示先激发i的父亲,再激发i,把i的整棵子树都激发的最小费用 f1,i表示先激发i,再激发i的父亲,把i的整棵子树都激发的最小费用 设x,y为 ...
- 【LOJ】#2041. 「SHOI2015」聚变反应炉
题解 这显然是一道题拆成两道 然后我胡乱分析了一波,决定第一题就用点度贪心(反正散播的能量肯定能被使用),然后过了 第二题开始mengbier 设\(f_u\)表示第u个点在父亲发动之后才发动的最小价 ...
- [暑假的bzoj刷水记录]
(这篇我就不信有网站来扣) 这个暑假打算刷刷题啥的 但是写博客好累啊 堆一起算了 隔一段更新一下. 7月27号之前刷的的就不写了 , 写的累 代码不贴了,可以找我要啊.. 2017.8.27upd ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- SHOI做题记录
LOJ #2027. 「SHOI2016」黑暗前的幻想乡 考虑到每个公司一条边,那就等价于没有任何一家公司没有边. 然后就可以容斥+矩阵树定理,没了. LOJ #2028. 「SHOI2016」随机序 ...
- 微信小程序开发视频教程新鲜出炉
微信小程序开发公测了,可是对于新手来说,不同的框架不同的开发机制,如何快速适应呢?微信小程序开发视频教程新鲜出炉了,从零开始一步一步搭建微信小程序,每个章节都会涉及到不同的知识点,等教程学习完你不但掌 ...
- 刚写完的商城erp + 这个商城前台,新鲜出炉。自己1个人写, 包括php框架和前端html页面.
刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面. 刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面.
- 23套新鲜出炉的网站和手机界面 PSD 素材
Web 用户界面,移动用户界面和线框套件对设计师很有用,因为这些套件让他们使用快速和有效的方式复制用户界面.这些类型的工具包提供了一个基本的用户界面元素,用于它们需要制作的网站或软件模型. 在这篇文章 ...
随机推荐
- Windows 查看当前登录用户名
使用 PowerShell 输入 whoami,PowerShell 将以 hostname\username 的方式输出主机名和用户名: $ whoami hostname\username 使用 ...
- 【图文安装教程】在docker中安装ES
在docker中安装ES怎么安装?本文就教大家怎么安装 1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器,因此需要让es和kibana容器互联.这里先创建一个网络: docker ...
- 严蔚敏 数据结构 配套教材 PDF
目录 严蔚敏 数据结构 配套教材 PDF 下载地址: 严蔚敏 数据结构 配套教材 PDF 配套教材包括: 严蔚敏<数据结构题集>(C语言版).pdf 严蔚敏<数据结构>(C语言 ...
- 搭建MyBatis环境
开发环境 idea .maven .MySQL.MyBatis MySQL不同版本的注意事项 1.驱动类driver-class-name MySQL 5版本使用jdbc5驱动,驱动类使用:com.m ...
- nacos未授权访问漏洞,导致被网警找
背景 公司收购了另一家公司,所以相应的后端服务和服务器都交给我管理,但是没有任何的交接文档,大概看了一下代码,依赖的东西就去忙别的了. 直到今天网警突然打电话给我说系统有漏洞(CVE-2021-294 ...
- Google Ads – UTM
介绍 UTM (Urchin tracking module) 的作用是帮助我们收集访客的来源渠道. 比如说, 用户是从 Google 广告来的, Youtube, 还是 Facebook 等等. 它 ...
- SQL Server CTE (Common Table Expression) 公用表表达式
参考: Sql - CTE公用表表达式和With用法总结 YouTube – SQL WITH Clause | How to write SQL Queries using WITH Clause ...
- 反DDD模式之关系型数据库
本文书接上回<图穷匕见-所有反DDD模式都是垃圾>,关注公众号(老肖想当外语大佬)获取信息: 最新文章更新: DDD框架源码(.NET.Java双平台): 加群畅聊,建模分析.技术实现交流 ...
- Linux下挂载SD卡,以及容易犯的误区
1.插入SD卡 如果系统能够识别SD卡,则会打印一些信息: 2.查看系统给SD卡分配的设备名 命令如下: fdisk -l 说明:通常是根据SD卡的存储容量来确定的. 比如下面的信息: 3.挂载SD卡 ...
- Nuxt.js 应用中的 app:beforeMount 钩子详解
title: Nuxt.js 应用中的 app:beforeMount 钩子详解 date: 2024/10/4 updated: 2024/10/4 author: cmdragon excerpt ...