P8564 ρars/ey 题解

显然树上背包。

首先一眼会想到的状态:dpi,j 表示 i 的子树最后剩下 j 个结点的最小代价。

然而开始写会发现这并不好 DP。

于是我们换一个想法:dpi,j 表示 i 的子树删去 j 个结点的最小代价。

则有转移方程:

dpi,j=minvson(i){dpi,jk+dpv,k}

但是注意到这个方程 j 最多到 sizi1cntsonicntsoni 表示 i 的儿子的数量),我们还需要一个方程:

dpi,sizi1=min{dpi,j+fsizij}

于是这样就完美了,O(n2) 足够通过此题

代码如下:

#include<bits/stdc++.h> #define MAXN 5010 #define INF 0x7f7f7f7f7f7f7f7f using namespace std; typedef long long ll; struct edge{ int pre, to; }; edge e[MAXN << 1]; int n, cnt; int head[MAXN], f[MAXN]; namespace strange{ ll dp[MAXN][MAXN], siz[MAXN]; void dfs(int now, int fa){ dp[now][0] = 0; siz[now] = 1; for(int i = head[now]; i; i = e[i].pre){ if(e[i].to == fa) continue; dfs(e[i].to, now); for(int j = siz[now] + siz[e[i].to] - 1; j > 0; j--){ for(int k = max(j - siz[now], 1ll); k <= siz[e[i].to] - 1 && k <= j; k++){ if(dp[e[i].to][k] >= INF || dp[now][j - k] >= INF) continue; dp[now][j] = min(dp[now][j], dp[e[i].to][k] + dp[now][j - k]); } } siz[now] += siz[e[i].to];//记得先 DP 后加 siz,否则复杂度是假的,这个蒟蒻就是因为这个少了 30 分 } for(int j = 0; j < siz[now] - 1; j++){ dp[now][siz[now] - 1] = min(dp[now][siz[now] - 1], dp[now][j] + f[siz[now] - j]); } } void main(){ memset(dp, 0x7f, sizeof(dp)); dfs(1, 0); printf("%lld\n",dp[1][siz[1] - 1]); } } void add_edge(int u, int v){ e[++cnt].pre = head[u]; e[cnt].to = v; head[u] = cnt; } int main(){ // freopen("T2ex2.in", "r", stdin); scanf("%d",&n); for(int i = 1; i < n; i++) scanf("%d",&f[i + 1]); for(int i = 1; i < n; i++){ int u, v; scanf("%d%d",&u,&v); add_edge(u, v); add_edge(v, u); } strange::main(); return 0; }

__EOF__

本文作者NightTide
本文链接https://www.cnblogs.com/NightTide/p/18434019.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Night_Tide  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示