题目描述

  公园里有$n$个雕像,有$n-1$条道路分别连接其中两个雕像,任意两个雕像可以直接或间接相连。现在每个景点$i$聚集着$P_i$只鸽子,旅行家手里有$v$数量的面包屑。
  一旦旅行家在雕像$i$撒下$1$单位面包屑,那么相邻的雕像的鸽子就都会飞到雕像$i$来觅食。
  时间线是这样的:首先,旅行家到达雕像$i$并与$P_i$鸽子会面。然后,他放下$1$单位面包屑。他离开雕像。在旅行家到达下一座雕像之前,来自相邻雕像的鸽子移动到雕像$i$(所以这些鸽子不计入他遇到的鸽子数)。注意旅行家每到一达雕像可以撒下面包屑,也可以不撒。
  旅行家可以在任何一座雕像上进入公园,沿着一些道路走下去(但不要使用同一道路两次),然后离开公园。
  在旅行家离开公园后,没有面包屑的小学生将进入并穿越完全相同的路线,并遇见许多群鸽子。
  通过最多$v$单位面包屑,旅行家希望最大化旅行家在路线上遇到的鸽子数量与小学生遇到的鸽子数量之间的差异。


输入格式

第一行两个整数$n,v$
第二行$n$个数为$P_i$
接下来$n-1$,每行两个整数,$X_i,Y_i$表示$X_i$与$Y_i$雕像相连


输出格式

输出只有一行,表示答案


样例

样例输入:

12 2
2 3 3 8 1 5 6 7 8 3 5 4
2 1
2 7
3 4  
4 7  
7 6  
5 6  
6 8  
6 9
7 10
10 11
10 12

样例输出:

36


数据范围与提示

样例解释:

一个可行的方案:旅行家从雕像$6$进入公园。在那里他遇到了$5$只鸽子。他放下面包屑。$p_6$现在是$27$,$p_5=p_7=p_8=p_9=0$。接下来,他跑向雕像$7$并遇到$0$鸽子。他撒下了第二个面包屑。$p_7=41$且$p_2=p_4=p_6=p_{10}=0$。他离开公园,他总共遇见$5+0=5$只鸽子。小学生跟着他走过同样的路线,但遇到$p_6+p_7=0+41=41$只鸽子。差是$41-5=36$。

数据范围:

对于$20\%$的数据,$1\leqslant n\leqslant 10$
对于另外$20\%$的数据,$1\leqslant n\leqslant 1,000$
对于另外$30\%$的数据,存在一个可行的最优方案从$1$出发
对于另外$30\%$的数据无特殊限制
对于$100\%$的数据,$1\leqslant n\leqslant 10^5,0\leqslant v\leqslant 100,0\leqslant P_i\leqslant 10^9$


题解

原题见$CEOI2017\ Chase$,我也不知道玄学出题人改的什么玄学题面……

一看就是$DP$题,但是显然我们不能枚举起点。

但是我们还是要先想一下枚举端点的做法,做事要慢慢来~

我的做法是设$dp[i][j][0/1]$表示到了$i$号点,已经撒了$j$次,在当前节点有没有撒的最大收益,转移是这样的:

$$dp[i][j][0]=max(dp[fa][j][0],dp[fa][j][1]) \\ dp[i][j][1]=max(dp[fa][j-1][0],dp[fa][j-1][1])+sum[i]-p[fa]$$

其中$sum[i]$表示在$i$号点撒会引来$sum[i]$只鸽子,不含$i$号点本身就有的,如下图$\downarrow$

$sum[i]$是指$\sum \limits_{i=1}^4 p_i$。

直接这样做会$TLE\ 44$,如果我们加上$clock()$的话可以得到$74\sim 78$不等。

那么我们现在考虑满分解法,如何快速求出以每个点为起点的最大贡献,将其取$\max$即可。

考虑定义两个数组$up[i][j]$和$down[i][j]$分别表示从$i$的子树走向$i$和从$i$走向$i$的子树,撒了$j$次的最大贡献。

然后状态转移是这样的:

$$up[i][j]=\max(up[i][j],up[son][j],up[son][j-1]+sum[i]-p[son]) \\ down[i][j]=\max(down[i][j],down[son][j],down[son][j-1]+sum[i]-p[fa])$$

还需要注意一点,如下图$\downarrow$

两种走法的最大贡献不一定相等,于是我们要正序枚举一遍所有的儿子,再倒着枚举一遍即可。

时间复杂度:$\Theta(n\times v)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,v;
int p[100001];
long long sum[100001];
long long dp[2][100001][101];
long long ans;
vector<int> e[100001];
void dfs(int x,int fa)
{
for(int i=1;i<=v;i++)
{
dp[0][x][i]=sum[x];
dp[1][x][i]=sum[x]-p[fa];
}
for(int i=0;i<e[x].size();i++)
if(e[x][i]!=fa)
{
dfs(e[x][i],x);
for(int j=1;j<v;j++)ans=max(ans,dp[0][x][j]+dp[1][e[x][i]][v-j]);
for(int j=1;j<=v;j++)
{
dp[0][x][j]=max(dp[0][x][j],max(dp[0][e[x][i]][j],dp[0][e[x][i]][j-1]+sum[x]-p[e[x][i]]));
dp[1][x][j]=max(dp[1][x][j],max(dp[1][e[x][i]][j],dp[1][e[x][i]][j-1]+sum[x]-p[fa]));
}
}
reverse(e[x].begin(),e[x].end());
for(int i=1;i<=v;i++)
{
dp[0][x][i]=sum[x];
dp[1][x][i]=sum[x]-p[fa];
}
for(int i=0;i<e[x].size();i++)
if(e[x][i]!=fa)
{
for(int j=1;j<v;j++)ans=max(ans,dp[0][x][j]+dp[1][e[x][i]][v-j]);
for(int j=1;j<=v;j++)
{
dp[0][x][j]=max(dp[0][x][j],max(dp[0][e[x][i]][j],dp[0][e[x][i]][j-1]+sum[x]-p[e[x][i]]));
dp[1][x][j]=max(dp[1][x][j],max(dp[1][e[x][i]][j],dp[1][e[x][i]][j-1]+sum[x]-p[fa]));
}
}
ans=max(ans,max(dp[0][x][v],dp[1][x][v]));
}
int main()
{
scanf("%d%d",&n,&v);if(!v){puts("0");return 0;}
for(int i=1;i<=n;i++)scanf("%d",&p[i]);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
sum[x]+=p[y];
sum[y]+=p[x];
}
dfs(1,0);
printf("%lld",ans);
return 0;
}

rp++

[CSP-S模拟测试]:Park(树上DP)的更多相关文章

  1. [CSP-S模拟测试]:B(DP+数学)

    题目传送门(内部题45) 输入格式 第一行$3$个整数$n,m,P$.第二行$m$个整数,表示$m$次询问. 输出格式 一行$m$个整数表示答案. 样例 样例输入1: 2 4 40 1 2 3 样例输 ...

  2. [CSP-S模拟测试]:蛇(DP+构造+哈希)

    题目传送门(内部题140) 输入格式 前两行有两个长度相同的字符串,描述林先森花园上的字母. 第三行一个字符串$S$. 输出格式 输出一行一个整数,表示有多少种可能的蛇,对$10^9+7$取模. 样例 ...

  3. [CSP-S模拟测试]:最小值(DP+乱搞)

    题目背景 $Maxtir$更喜欢序列的最小值. 题目传送门(内部题128) 输入格式 第一行输入一个正整数$n$和四个整数$A,B,C,D$. 第二行输入$n$个整数,第$i$个数表示$a_i$. 输 ...

  4. [CSP-S模拟测试]:花(DP)

    题目传送门(内部题111) 输入格式 一个整数$T$,表示测试数据组数. 每组测试数据占一行,两个整数,分别表示$L$和$S$. 输出格式 对每组数据,输出一个整数表示答案. 样例 样例输入1: 13 ...

  5. [CSP-S模拟测试]:计数(DP+记忆化搜索)

    题目描述 既然是萌萌哒$visit\text{_}world$的比赛,那必然会有一道计数题啦!考虑一个$N$个节点的二叉树,它的节点被标上了$1\sim N$的编号.并且,编号为$i$的节点在二叉树的 ...

  6. [CSP-S模拟测试]:matrix(DP)

    题目描述 求出满足以下条件的$n\times m$的$01$矩阵个数:(1)第$i$行第$1~l_i$列恰好有$1$个$1$.(2)第$i$行第$r_i~m$列恰好有$1$个$1$.(3)每列至多有$ ...

  7. [CSP-S模拟测试]:题(DP+数学)

    题目描述 出个题就好了.这就是出题人没有写题目背景的原因.你在平面直角坐标系上.你一开始位于$(0,0)$.每次可以在上/下/左/右四个方向中选一个走一步.即:从$(x,y)$走到$(x,y+1),( ...

  8. [CSP-S模拟测试]:题(DP)

    题目描述 由于出题人赶时间所以没办法编故事来作为背景.一开始有$n$个苹果,$m$个人依次来吃苹果,第$i$个人会尝试吃$u_i$或$v_i$号苹果,具体来说分三种情况.$\bullet 1.$两个苹 ...

  9. [CSP-S模拟测试]:y(DP+bitset)

    题目背景 $\frac{1}{4}$遇到了一道水题,叕完全不会做,于是去请教小$D$.小$D$懒得理$\frac{1}{4}$,直接就离开了.于是,$\frac{1}{4}$只好来问你,这道题是这样的 ...

随机推荐

  1. hbase迁移快照ExportSnapshot时遇到的错

    1.Cannot allocate memory 报错信息: Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x ...

  2. PHP 距离我最近排序+二维数组按指定列排序

    思路: 1.获取我的位置,即:我的经纬度 2.各站点须有位置     即:排序对象有位置经纬度 3.查询要排序的站点列表 4.循环遍历计算  与我的距离 5.二维数组按 指定列(距离)排序 具体如下: ...

  3. 应用安全-安全设备-Waf系列-软Waf-云锁

    安装 安装 - Linux 前提:检查selinux状态 - 关闭selinux getenforce #显示为disabled则为关闭 .下载 x86:wget http://download.yu ...

  4. MVC Html.AntiForgeryToken(); 防止跨站伪造请求(建议所有表单提交都加这个)

    视图页面from表单中添加 @Html.AntiForgeryToken(); 然后每个表单提交的时候都会带__RequestVerificationToken 字段 后端控制器验证时添加  [Val ...

  5. Web高级 JavaScript中的算法

    算法 排序算法 稳定排序 待排序序列中相等元素在排序完成后,原有先后顺序不变. 非稳定排序 有序度 待排序序列中有序关系的元素对个数. 逆序度 1. 插入排序 遍历有序数组,对比待插入的元素大小,找到 ...

  6. 前端 CSS的选择器 伪类选择器

    伪类选择器 常用的几种伪类选择器. 伪类选择器一般会用在超链接a标签中 没有访问的超链接a标签样式: a:link { color: blue; } <!DOCTYPE html> < ...

  7. [Python3] 020 借函数,谈一谈变量的作用域

    目录 1. 概述 2. 分类 3. 变量的作用范围 少废话,上例子 4. 将局部变量提升为全局变量 少废话,上例子 5. 内建函数 globals() 与 locals() 少废话,上例子 6. 邪恶 ...

  8. CodeForces 877E DFS序+线段树

    CodeForces 877E DFS序+线段树 题意 就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身 ...

  9. 开发一个 Parcel-vue 脚手架工具

    前言 像我们熟悉的 vue-cli,create-react-app 等脚手架,只需要输入简单的命令 vue init webpack project,即可快速帮我们生成一个初始项目.在实际工作中,我 ...

  10. CentOS6.4下Mysql数据库的安装与配置,导入数据库,授权远程ip

    卸载掉原有mysql 由于mysql数据库在Linux上实在是太流行了,所以眼下下载的主流Linux系统版本号基本上都集成了mysql数据库在里面,我们能够通过例如以下命令来查看我们的操作系统上是否已 ...