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+c[v]]=\min(dp[u][i][j+c[v]],tmp[u][i-1][j]+dp[v][0])\\
tmp[u][i][j]=\min(dp[u][i][j],tmp[u][i-1][j]+dp[v][1])
\]

不难发现我们这是一个树上背包,我们对其使用滚动数组优化。

\[tmp[u][cur][j+c[v]]=\min(dp[u][cur][j+c[v]],tmp[u][cur\oplus 1][j]+dp[v][0])\\
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][0]=\min_{i=0}^{sum} (dp[u][0],\max(tmp[i],tmp[i]-i+d[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 聚变反应炉的更多相关文章

  1. 洛谷 P4269 / loj 2041 [SHOI2015] 聚变反应炉 题解【贪心】【DP】

    树上游戏..二合一? 题目描述 曾经发明了零件组装机的发明家 SHTSC 又公开了他的新发明:聚变反应炉--一种可以产生大量清洁能量的神秘装置. 众所周知,利用核聚变产生的能量有两个难点:一是控制核聚 ...

  2. [SHOI2015]聚变反应炉[树dp、贪心]

    题意 给定一棵 \(n\) 个点的树,每个点有一个启动能量 \(d\) 和传递能量 \(c\) ,如果一个点被启动了,就会向和他直接相连的点发送 \(c\) 的能量,初始所有节点能量为0,问最少多少能 ...

  3. bzoj4593: [Shoi2015]聚变反应炉

    这道题的难点其实是在设DP方程,见过就应该会了 令f0,i表示先激发i的父亲,再激发i,把i的整棵子树都激发的最小费用 f1,i表示先激发i,再激发i的父亲,把i的整棵子树都激发的最小费用 设x,y为 ...

  4. 【LOJ】#2041. 「SHOI2015」聚变反应炉

    题解 这显然是一道题拆成两道 然后我胡乱分析了一波,决定第一题就用点度贪心(反正散播的能量肯定能被使用),然后过了 第二题开始mengbier 设\(f_u\)表示第u个点在父亲发动之后才发动的最小价 ...

  5. [暑假的bzoj刷水记录]

    (这篇我就不信有网站来扣) 这个暑假打算刷刷题啥的 但是写博客好累啊  堆一起算了 隔一段更新一下.  7月27号之前刷的的就不写了 , 写的累 代码不贴了,可以找我要啊.. 2017.8.27upd ...

  6. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  7. SHOI做题记录

    LOJ #2027. 「SHOI2016」黑暗前的幻想乡 考虑到每个公司一条边,那就等价于没有任何一家公司没有边. 然后就可以容斥+矩阵树定理,没了. LOJ #2028. 「SHOI2016」随机序 ...

  8. 微信小程序开发视频教程新鲜出炉

    微信小程序开发公测了,可是对于新手来说,不同的框架不同的开发机制,如何快速适应呢?微信小程序开发视频教程新鲜出炉了,从零开始一步一步搭建微信小程序,每个章节都会涉及到不同的知识点,等教程学习完你不但掌 ...

  9. 刚写完的商城erp + 这个商城前台,新鲜出炉。自己1个人写, 包括php框架和前端html页面.

    刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面. 刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面.

  10. 23套新鲜出炉的网站和手机界面 PSD 素材

    Web 用户界面,移动用户界面和线框套件对设计师很有用,因为这些套件让他们使用快速和有效的方式复制用户界面.这些类型的工具包提供了一个基本的用户界面元素,用于它们需要制作的网站或软件模型. 在这篇文章 ...

随机推荐

  1. Es java API官网手册

    官方地址: 一.TransportClient客户端 https://www.elastic.co/guide/en/elasticsearch/client/java-api/7.5/index.h ...

  2. Maven 打 JAR 包

    项目和依赖分别打入独立 JAR 包 使用 Maven Jar Plugin 插件,可以将项目自身单独打成一个 JAR 包,项目依赖的 JAR 包统一放置到指定目录. 在项目的 pom.xml 中添加如 ...

  3. Coursera self-driving2, State Estimation and Localization Week4, LIDAR

    operating principles 工作原理 Velodyne 加州,Hokuyo 日本,SICK 德国 TOF 就是用发出去收到的时间差和光速算距离 basic LIDAR models (2 ...

  4. postgresql数据库中 JSON 字段 replace

    一.需求 postgresql 数据库,需要将某些表中的json字段的数据进行替换. 二.做法 思路:将json字段转为text,然后调用replace函数后,将text再转为json update ...

  5. Pointer Event Api-整合鼠标事件、触摸和触控笔事件

    Pointer Events API 是Hmtl5的事件规范之一,它主要目的是用来将鼠标(Mouse).触摸(touch)和触控笔(pen)三种事件整合为统一的API. Pointer Event P ...

  6. DNN、CNN、RNN的区别

    参考1:CNN.RNN.DNN区别 参考2:一文读懂 CNN.DNN.RNN 内部网络结构区别 一张图解释所有: 感知机(输入层.输出层.一个隐藏层)-->不能解决复杂的函数-->神经网络 ...

  7. Angular 18+ 高级教程 – Component 组件 の Angular Component vs Web Component

    前言 在 初识 Angular 中我有提到, Angular 团队是一群不爱创新.爱 follow 标准.爱小题大做的一群人. 所以,要理解 Angular Component,我们就非得要先搞懂远古 ...

  8. ASP.NET Core – Web API Versioning

    前言 项目持续维护, API 就需要版本控制. ASP.NET Core 有官方的插件专门处理 API 版本控制. 主要参考 Your Guide to REST API Versioning in ...

  9. 嵌入式Linux ubi文件系统制作、分区设置、只读文件系统,uboot启动参数root

    当前平台, 基于君正的X10000平台的嵌入式Linux 系统 0  目的 我要设置根文件系统为可读写, 设置data分区上的文件系统为只读 1 设置各文件系统的读写属性 /bin/mount -o ...

  10. LinearRegression线性回归

    1.LinearRegression将方程分为两个部分存放,coef_存放回归系数,intercept_则存放截距,因此要查看方程,就是查看这两个变量的取值. 2.回归系数(regression co ...