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. 【LLM训练系列】NanoGPT源码详解和中文GPT训练实践

    本文是[训练LLM系列]的第一篇,主要重点介绍NanoGPT代码以及中文.英文预训练实践.最新版参见我的知乎:https://zhuanlan.zhihu.com/p/716442447 除跑通原始N ...

  2. 使用 Nuxt 的 showError 显示全屏错误页面

    title: 使用 Nuxt 的 showError 显示全屏错误页面 date: 2024/8/26 updated: 2024/8/26 author: cmdragon excerpt: 摘要: ...

  3. 基于surging 如何利用peerjs进行语音视频通话

    一 . 概述 PeerJS 是一个基于浏览器WebRTC功能实现的js功能包,简化了WebrRTC的开发过程,对底层的细节做了封装,直接调用API即可,再配合surging 协议组件化从而做到稳定,高 ...

  4. 远距离跨网络实现windows远程桌面连接

    1.保证已经打开被连接电脑---远程访问---权限. 我的电脑--右键--属性--远程设置 2.选择允许连接 (选择用户和高级没有特殊设置可以不动,被连接电脑当前登陆的账号就可以满足权限) 3.打开- ...

  5. 【YashanDB数据库】YAS-02032 column type is incompatible with referenced column type

    [标题]错误码处理 [问题分类]外键约束创建报错 [关键字]YAS-02032 [问题描述]设置外键约束报错,数据元数据不正确. [问题原因分析]外键字段类型不支持,比如varchar2(64) ,指 ...

  6. PicGo RequestError: Error: tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:36677

    PicGo RequestError: Error: tunneling socket could not be established, cause=connect ECONNREFUSED 127 ...

  7. C#阿里境外服务器部署企业邮箱发邮件代码

    static string accountName = "发件人邮箱"; static string password = "发件人邮箱密码"; static ...

  8. Angular 18+ 高级教程 – Routing 路由 (原理篇)

    修改中... 前言 Angular 是 Single Page Application (SPA) 单页面应用,所谓的单页面是站在服务端的角度看,不管游览器请求什么路径,一律返回 index.html ...

  9. CSS & JS Effect – Blue Tick Avatar

    效果 难点 难题只有一个, 那就是如何把 blue tick image 定位当 avatar 的右下角. HTML <div class="avatar-wrapper"& ...

  10. httpclient调用接口

    有时候会将参数(返回结果)压缩(解压),加密(解密) 将json参数通过GZip压缩 Base64加密 1 public static String gzipAndEncryption(String ...