哨戒炮 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)的更多相关文章

  1. 2021.07.17 P3177 树上染色(树形DP)

    2021.07.17 P3177 树上染色(树形DP) [P3177 HAOI2015]树上染色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 重点: 1.dp思想是需要什么,维护 ...

  2. [SHOI2008]仙人掌图 II——树形dp与环形处理

    题意: 给定一个仙人掌,边权为1 距离定义为两个点之间的最短路径 直径定义为距离最远的两个点的距离 求仙人掌直径 题解: 类比树形dp求直径. f[i]表示i向下最多多长 处理链的话,直接dp即可. ...

  3. 2019.02.07 bzoj4784: [Zjoi2017]仙人掌(仙人掌+树形dp)

    传送门 题意:给一个无向连通图,问给它加边形成仙人掌的方案数. 思路: 先考虑给一棵树加边形成仙人掌的方案数. 这个显然可以做树形dp. fif_ifi​表示把iii为根的子树加边形成仙人掌的方案数. ...

  4. 2018.07.22 洛谷P3047附近的牛(树形dp)

    传送门 给出一棵n" role="presentation" style="position: relative;">nn个点的树,每个点上有C ...

  5. 2018.07.22 洛谷P2986 伟大的奶牛聚集(树形dp)

    传送门 给出一棵树,树有边权和点权,若选定一个点作为中心,这棵树的代价是所有点权乘上到根的距离的和.求代价最小. 解法:一道明显的换根dp" role="presentation& ...

  6. 2018.07.22 codeforces750E(线段树维护状态转移)

    传送门 给出一个数字字串,给出若干个询问,询问在字串的一段区间保证出现2017" role="presentation" style="position: re ...

  7. 2018.07.22 洛谷P4316 绿豆蛙的归宿(概率dp)

    传送门 简单的递推. 由于是DAG" role="presentation" style="position: relative;">DAGDA ...

  8. 2018.07.22 洛谷P1967 货车运输(kruskal重构树)

    传送门 这道题以前只会树剖和最小生成树+倍增. 而现在学习了一个叫做kruskal" role="presentation" style="position: ...

  9. 2018.07.22 洛谷P3106 GPS的决斗Dueling GPS's(最短路)

    传送门 图论模拟题. 这题直接写3个(可以压成一个)spfa" role="presentation" style="position: relative;&q ...

随机推荐

  1. html的基本数据类型(数字,字符串, 列表, 字典)

    基本数据类型 1. 数字 a = 18 ; 2. 字符串 a = 'alex'a.chartAt(索引位置)a.substring(起始位置, 借宿位置)a.length 获取当前字符串长度a.tri ...

  2. Python Spider 抓取猫眼电影TOP100

    """ 抓取猫眼电影TOP100 """ import re import time import requests from bs4 im ...

  3. Mysql binlog二进制日志

    Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的实际原sql语句都会被记录在binlog中. 优点:不需要记录每一 ...

  4. 使用github的流程

    使用github的流程 在实际项目开发中,按照如下步骤使用git进行代码管理 1.项目经理在开发之初,创建好仓库,上传项目的框架.组员分支 2.组员克隆项目框架,同步分支,按分工开发,在分支提交代码 ...

  5. 线性判别分析LDA详解

    1 Linear Discriminant Analysis    相较于FLD(Fisher Linear Decriminant),LDA假设:1.样本数据服从正态分布,2.各类得协方差相等.虽然 ...

  6. js 获取input选择的图片的信息

    1JS $("#btn").click(function () { var imageEle = document.getElementById("images" ...

  7. LinuxI/O 性能分析

    .I/O linux 命令: ostat 监视I/O子系统 iostat [参数][时间][次数] 通过iostat方便查看CPU.网卡.tty设备.磁盘.CD-ROM 等等设备的活动情况, 负载信息 ...

  8. Analyzing Microarray Data with R

    1) 熟悉CEL file 从 NCBI GEO (http://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE24460)下载GSE24460. 将得到 ...

  9. pip批量更新安装的包

    ------------------pip批量更新库-------------------- 1)查看过期的库 pip list --outdated  更新单一的库: pip install --u ...

  10. 大型运输行业实战_day04_1_搭建ssm框架最容易犯的错误

    错误1.MapperScannerConfigurer中应该去扫描包,而不是接口 如果出现上述错误,报错如下,注意我们在看报错日志的时候一点要从 后往前看 错误2.没有配置别名,又要使用别名 命名不规 ...