博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ACdream1032(树形DP)
阅读量:6329 次
发布时间:2019-06-22

本文共 1555 字,大约阅读时间需要 5 分钟。

题意

给出一棵树,每个节点有权值,问由 \(1\) ~ \(n\) 个节点组成的树块的权值和的最小值。

分析

首先发现 \(n\) 很小,那么我们可以开一个二维数组 \(dp[i][j]\) 表示以 \(i\) 节点为树块的根节点且树块中节点的数量为 \(j\) 时的最小值。

\(u\) 节点出发,先去遍历子树,再用子树的那个根节点 \(v\) 去更新 \(u\) 的值。

code

#include
#include
#include
#include
using namespace std;typedef long long ll;const int MAXN = 2e3 + 10;const ll INF = 1e18;int n;int w[MAXN];vector
G[MAXN];ll dp[MAXN][MAXN];int sons[MAXN];void dfs(int fa, int u) { dp[u][1] = w[u]; sons[u] = 1; for(int i = 0; i < (int)G[u].size(); i++) { int v = G[u][i]; if(v != fa) { dfs(u, v); sons[u] += sons[v]; for(int j = sons[u]; j >= 1; j--) { for(int k = 1; k <= sons[v]; k++) { if(j <= k) break; if(dp[v][k] == INF) break; dp[u][j] = min(dp[u][j], dp[u][j - k] + dp[v][k]); } } } }}int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { dp[i][j] = INF; } scanf("%d", &w[i]); } for(int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } dfs(-1, 1); for(int i = 1; i <= n; i++) { ll ans = INF; for(int j = 1; j <= n; j++) { ans = min(ans, dp[j][i]); } printf("%lld%c", ans, " \n"[i == n]); } return 0;}

转载于:https://www.cnblogs.com/ftae/p/7247760.html

你可能感兴趣的文章
Redis从单机到集群,一步步教你环境部署以及使用
查看>>
【note】EtherCAT Configurator 使用之主菜单介绍
查看>>
iOS获取当前城市
查看>>
浅谈数据库联合查询
查看>>
可视化机器学习工具软件的比较分析研究
查看>>
OpenCV矩形检测
查看>>
InnoDB Master Thread I/O Rate详解
查看>>
org.apache.axis2.AxisFault: unknown
查看>>
Transport scheme NOT recognized: [stomp]
查看>>
用户与磁盘
查看>>
Oracle 10g通过创建物化视图实现不同数据库间表级别的数据同步
查看>>
SIP业务基本知识
查看>>
fn project 试用之后的几个问题
查看>>
synchronized修饰普通方法,修饰静态方法,修饰代码块,修饰线程run方法 比较
查看>>
linux-0.11内核 调试教程+GCC源代码
查看>>
IDEA快捷键大全
查看>>
在XML里的XSD和DTD以及standalone的使用3----具体使用详解
查看>>
《微信小程序七日谈》- 第四天:页面路径最多五层?导航可以这么玩
查看>>
linux用户密码生成
查看>>
Python图像处理(11):k均值
查看>>