2018.07.22哨戒炮 II(树形dp)
哨戒炮 II
描述
你的防线成功升级,从原来的一根线变成了一棵树。这棵树有 N 个炮台,炮台与炮台之间 有 N-1 条隧道。你要选择一些炮台安装哨戒炮。在第 i 个炮台上安装哨戒炮得到的防御力为 vi。上次说过,哨戒炮离得太近会产生神奇的效果。具体来说,对于炮台 i,如果它安装了 哨戒炮且和 k 个哨戒炮用隧道直接相连,那么其防御力会变化 k*di。其中 di 为炮台 i 的抗 干扰属性值。如果为正,干扰对其有正的作用;为负,干扰对其有负的作用;为 0,则完全 不受干扰。
你的整套防线的防御力为所有哨戒炮的防御力之和。求防线的最大防御力
输入
第一行一个整数 N,表示炮台数量。
第二行 N 个整数表示 vi。
第三行 N 个整数表示 di。
接下来 N-1 行每行两个整数描述一条隧道。
输出
输出一行一个整数表示答案
样例输入
2
1 1
0 0
1 2
样例输出
2
提示
对于 20%的数据,N <= 20。
对于 40%的数据,N <= 100。
对于 70%的数据,N <= 5000。
对于 100%的数据,N <= 100000
这题杠了40min然后发现读优写挂了。
事实上状态转移方程最开始推对了啊233。。。
不难看出这是一道树形dp" role="presentation" style="position: relative;">dpdp。
我们用fi,0/1" role="presentation" style="position: relative;">fi,0/1fi,0/1表示当前在标号为i" role="presentation" style="position: relative;">ii的节点,当前节点安放哨戒炮/没有安放哨戒炮。
然后dfs" role="presentation" style="position: relative;">dfsdfs的时候用一点小技巧(瞎yy" role="presentation" style="position: relative;">yyyy的),就是每次dfs" role="presentation" style="position: relative;">dfsdfs的时候并不考虑题目中说的di" role="presentation" style="position: relative;">didi的影响,而是将这个影响转移给儿子,比如说,我们当前选了u" role="presentation" style="position: relative;">uu,然后准备从选择儿子v" role="presentation" style="position: relative;">vv的情况向当前情况转移,就可以在这一层dfs" role="presentation" style="position: relative;">dfsdfs的时候放弃计算d[p]" role="presentation" style="position: relative;">d[p]d[p]这个东西,而是在dfs" role="presentation" style="position: relative;">dfsdfs儿子v" role="presentation" style="position: relative;">vv的时候附加一个值sum" role="presentation" style="position: relative;">sumsum,在v" role="presentation" style="position: relative;">vv递归返回的时候加上这个值就行了。
但sum" role="presentation" style="position: relative;">sumsum的值如何计算呢?于是我们分情况考虑。
如果当前点u" role="presentation" style="position: relative;">uu没有被选,那么对儿子没有影响,因此无论儿子选还是不选,sum" role="presentation" style="position: relative;">sumsum值都为0" role="presentation" style="position: relative;">00。
那如果u" role="presentation" style="position: relative;">uu被选了呢?如果儿子不选,sum" role="presentation" style="position: relative;">sumsum值仍然为0" role="presentation" style="position: relative;">00,而如果儿子被选,显然总答案的值会加上d[u]+d[v]" role="presentation" style="position: relative;">d[u]+d[v]d[u]+d[v],因此sum" role="presentation" style="position: relative;">sumsum的值就等于d[u]+d[v]" role="presentation" style="position: relative;">d[u]+d[v]d[u]+d[v]。
这样一来可以轻松地写出状态转移方程了。
f[u][0]=∑max(f[v][0],f[v][1])" role="presentation" style="position: relative;">f[u][0]=∑max(f[v][0],f[v][1])f[u][0]=∑max(f[v][0],f[v][1])
f[u][1]=∑max(f[v][0],f[v][1]+d[u]+d[v])" role="presentation" style="position: relative;">f[u][1]=∑max(f[v][0],f[v][1]+d[u]+d[v])f[u][1]=∑max(f[v][0],f[v][1]+d[u]+d[v])
这样还是不够,要记得只有安放了哨戒炮的位置才能获得防御力v[i]" role="presentation" style="position: relative;">v[i]v[i],因此第二个状态转移方程事实上是错的。
应该是:f[u][1]=∑(max(f[v][0],f[v][1]+d[u]+d[v])+V[u])" role="presentation" style="position: relative;">f[u][1]=∑(max(f[v][0],f[v][1]+d[u]+d[v])+V[u])f[u][1]=∑(max(f[v][0],f[v][1]+d[u]+d[v])+V[u])
代码如下:
#include<bits/stdc++.h>
#define N 100005
#define ll long long
using namespace std;
ll dp[N][2],n,a[N],d[N],cnt=0,first[N];
struct Node{ll v,next;}e[N<<1];
inline ll read(){
ll ans=0,w=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans*w;
}
inline ll dfs(ll p,ll f,ll sum,ll fa){
if(dp[p][f]!=-1)return dp[p][f]+sum;
dp[p][f]=0;
if(f==0){
for(ll i=first[p];i;i=e[i].next){
ll v=e[i].v;
if(v==fa)continue;
dp[p][f]+=max(dfs(v,0,0,p),dfs(v,1,0,p));
}
return dp[p][f]+sum;
}
dp[p][f]=d[p];
for(ll i=first[p];i;i=e[i].next){
ll v=e[i].v;
if(v==fa)continue;
dp[p][f]+=max(dfs(v,0,0,p),dfs(v,1,a[p]+a[v],p));
}
return dp[p][f]+sum;
}
inline void add(ll u,ll v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;}
int main(){
memset(dp,-1,sizeof(dp));
n=read();
for(ll i=1;i<=n;++i)d[i]=read();
for(ll i=1;i<=n;++i)a[i]=read();
for(ll i=1;i<n;++i){
ll u=read(),v=read();
add(u,v),add(v,u);
}
printf("%lld",max(dfs(1,0,0,1),dfs(1,1,0,1)));
return 0;
}
2018.07.22哨戒炮 II(树形dp)的更多相关文章
- 2021.07.17 P3177 树上染色(树形DP)
2021.07.17 P3177 树上染色(树形DP) [P3177 HAOI2015]树上染色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 重点: 1.dp思想是需要什么,维护 ...
- [SHOI2008]仙人掌图 II——树形dp与环形处理
题意: 给定一个仙人掌,边权为1 距离定义为两个点之间的最短路径 直径定义为距离最远的两个点的距离 求仙人掌直径 题解: 类比树形dp求直径. f[i]表示i向下最多多长 处理链的话,直接dp即可. ...
- 2019.02.07 bzoj4784: [Zjoi2017]仙人掌(仙人掌+树形dp)
传送门 题意:给一个无向连通图,问给它加边形成仙人掌的方案数. 思路: 先考虑给一棵树加边形成仙人掌的方案数. 这个显然可以做树形dp. fif_ifi表示把iii为根的子树加边形成仙人掌的方案数. ...
- 2018.07.22 洛谷P3047附近的牛(树形dp)
传送门 给出一棵n" role="presentation" style="position: relative;">nn个点的树,每个点上有C ...
- 2018.07.22 洛谷P2986 伟大的奶牛聚集(树形dp)
传送门 给出一棵树,树有边权和点权,若选定一个点作为中心,这棵树的代价是所有点权乘上到根的距离的和.求代价最小. 解法:一道明显的换根dp" role="presentation& ...
- 2018.07.22 codeforces750E(线段树维护状态转移)
传送门 给出一个数字字串,给出若干个询问,询问在字串的一段区间保证出现2017" role="presentation" style="position: re ...
- 2018.07.22 洛谷P4316 绿豆蛙的归宿(概率dp)
传送门 简单的递推. 由于是DAG" role="presentation" style="position: relative;">DAGDA ...
- 2018.07.22 洛谷P1967 货车运输(kruskal重构树)
传送门 这道题以前只会树剖和最小生成树+倍增. 而现在学习了一个叫做kruskal" role="presentation" style="position: ...
- 2018.07.22 洛谷P3106 GPS的决斗Dueling GPS's(最短路)
传送门 图论模拟题. 这题直接写3个(可以压成一个)spfa" role="presentation" style="position: relative;&q ...
随机推荐
- PadLeft 补零
补零 PadLeft -Caption.Length())+Caption; UnicodeString __fastcall StringOfChar(WideChar Ch, int Count) ...
- VB6 MsgBox 函数
在对话框中显示消息,等待用户单击按钮,并返回一个值指示用户单击的按钮. MsgBox(prompt[, buttons][, title][, helpfile, context]) 参数 promp ...
- 机器学习入门-随机森林预测温度-不同参数对结果的影响调参 1.RandomedSearchCV(随机参数组的选择) 2.GridSearchCV(网格参数搜索) 3.pprint(顺序打印) 4.rf.get_params(获得当前的输入参数)
使用了RamdomedSearchCV迭代100次,从参数组里面选择出当前最佳的参数组合 在RamdomedSearchCV的基础上,使用GridSearchCV在上面最佳参数的周围选择一些合适的参数 ...
- 13 python 常用的内置方法介绍
1.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object) ...
- pip cannot confirm SSL certificate: SSL module is not available
centos6.8编译安装python2.7之后,使用pip报错:pip cannot confirm SSL certificate: SSL module is not available 解决方 ...
- 基于 tensorflow 的 mnist 数据集预测
1. tensorflow 基本使用方法 2. mnist 数据集简介与预处理 3. 聚类算法模型 4. 使用卷积神经网络进行特征生成 5. 训练网络模型生成结果 how to install ten ...
- js 日期证有效性验的通用方法
开发的理念是“为复用而开发,为使用而组装”,代码的复用度将是项目和产品的一个重要的技术指标. var DateTools={ isDate:function(str) { var result = s ...
- js中常见的内置对象
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 【Java杂记】Equals 和 hashCode
equals 和 hashCode含义 equal:判断两个对象是否相等,如果相同,返回true 否则返回false hashcode: 返回一个int数 Object 默认(内部地址转化为一个数字) ...
- Conductor Server
安装 要求 数据库:Dynomite https://github.com/Netflix/dynomite 索引后端: Elasticsearch 2.x http ...