题目描述

  公园里有$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. idea 2017 快捷键

    Ctrl+Shift + Enter,语句完成 “!”,否定完成,输入表达式时按 “!”键 Ctrl+E,最近的文件 Ctrl+Shift+E,最近更改的文件 Shift+Click,可以关闭文件 C ...

  2. .Net core 3.0 SignalR+Vue 实现简单的即时通讯/聊天IM (无jq依赖)

    .Net core 中的SignalR JavaScript客户端已经不需要依赖Jquery了 一.服务端 1.nuget安装 Microsoft.AspNetCore.SignalR 2.在star ...

  3. JAVA的学习

    怎么说呢,我已经接触JAVA已经两周了,个人感觉还是不懂,哈哈,JAVA是一门编程语言,是大多数开发者较为习惯的编程模式,我感觉相对比C语言来说可能简单学点,可能是我先接触C语言把,或许因人而异把,在 ...

  4. C语言1-2019级秋季作业第一周作业

    1.你对软件工程专业或者计算机科学与技术专业了解是怎样? 软件工程专业是指对计算机的软件方面灵活掌控,开发软件的工程.软件工程其中会用到计算机科学.数学方面构建模型与算法:软件工程的目标就是开发出能够 ...

  5. [Web 前端] 019 css 定位之绝对定位与相对定位

    1. 关于定位 我们可以使用 css 的 position 属性来设置元素的定位类型 postion 的设置项如下 设置项 释义 relative 生成相对定位元素元素所占据的文档流的位置不变元素本身 ...

  6. [19/05/14-星期二] HTML_body标签(列表标签和图片标签)

    一.列表标签 <!-- 快捷键 1.<meta charset="UTF-8"/> 用m6可直接写出 2.复制当前1行到下一行 ctrl+shift+R --&g ...

  7. 【洛谷p1981】表达式求值

    题前废话: 咱也不知道咱写了个什么神奇的代码导致_rqy都看不明白它是怎么re掉的, 代码的大致思路是这样的:对于这样一个中缀表达式,先转化成它的后缀表达式的形式,然后利用P1449 后缀表达式 这道 ...

  8. Codeforces 840C 题解(DP+组合数学)

    题面 传送门:http://codeforces.com/problemset/problem/840/C C. On the Bench time limit per test2 seconds m ...

  9. bzoj3188 [Coci 2011]Upit(分块)

    Time Limit: 10 Sec  Memory Limit: 128 MB Description 你需要维护一个序列,支持以下4种操作.一,将区间(u,v)的数覆盖为C:二,将区间(u,v)的 ...

  10. log.info()传入多个参数的方法

    不知道项目里用的是啥 ** 版本的 log4j 居然不能传入变长参数 logger.info(String.format("%s %s %s", username, feature ...