bzoj4987 Tree 树上背包
题目传送门
https://lydsy.com/JudgeOnline/problem.php?id=4987
题解
一道还不错的题咯。
很容易发现一个结论:这 \(k\) 个点构成的一定是一个连通块,并且走的时候应该是按照某种类似于 dfs 的遍历方式连续走的。
可以发现,最终答案应该有:从根的某个子树走出来,到某个子树中去的这样的情况,也有可能是从根到某个子树中去的情况;同时,过程中会用到从根到子树中走一遍再回到根的情况。这三种情况都需要考虑。
于是进行树形 dp,令 \(dp[x][i][0/1/2]\) 表示以 \(x\) 为根的子树中,选择了 \(i\) 个点,情况为从根到子树中走一遍再回到根/从根到某个子树中去(等同于从某个子树到根)/从根的某个子树走出来,到某个子树中去这三种情况,转移的时候,第二维直接背包合并,第三维是这样的:\(0+0\to 0, 0+1\to 1, 1+0\to 1, 0+2\to 2,1+1\to 2,2+0\to 2\)。
代码如下,时间复杂度为一般的背包合并 \(O(nk)\)。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 3000 + 7;
const int INF = 0x3f3f3f3f;
int n, m, ans;
int dp[N][N][3], siz[N];
struct Edge { int to, ne, w; } g[N << 1]; int head[N], tot;
inline void addedge(int x, int y, int z) { g[++tot].to = y, g[tot].w = z, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y, int z) { addedge(x, y, z), addedge(y, x, z); }
inline void dfs(int x, int fa = 0) {
dp[x][1][0] = dp[x][1][1] = 0;
siz[x] = 1;
for fec(i, x, y) if (y != fa) {
dfs(y, x);
int w = g[i].w;
for (int i = std::min(m, siz[x]); i; --i)
for (int j = 1; j <= std::min(m, siz[y]); ++j) {
smin(dp[x][i + j][0], dp[x][i][0] + dp[y][j][0] + w * 2);
smin(dp[x][i + j][1], dp[x][i][0] + dp[y][j][1] + w);
smin(dp[x][i + j][1], dp[x][i][1] + dp[y][j][0] + w * 2);
smin(dp[x][i + j][2], dp[x][i][0] + dp[y][j][2] + w * 2);
smin(dp[x][i + j][2], dp[x][i][1] + dp[y][j][1] + w);
smin(dp[x][i + j][2], dp[x][i][2] + dp[y][j][0] + w * 2);
}
siz[x] += siz[y];
}
smin(ans, dp[x][m][0]), smin(ans, dp[x][m][1]), smin(ans, dp[x][m][2]);
// dbg("x = %d: ", x);
// for (int i = 1; i <= m; ++i) dbg("%d:(%d, %d, %d) ", i, dp[x][i][0], dp[x][i][1], dp[x][i][2]);
// dbg("\n");
}
inline void work() {
memset(dp, 0x3f, sizeof(dp));
ans = INF;
dfs(1);
printf("%d\n", ans);
}
inline void init() {
read(n), read(m);
int x, y, z;
for (int i = 1; i < n; ++i) read(x), read(y), read(z), adde(x, y, z);
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
bzoj4987 Tree 树上背包的更多相关文章
- hdu 1011 Starship Troopers(树上背包)
Problem Description You, the leader of Starship Troopers, are sent to destroy a base of the bugs. Th ...
- [U53204] 树上背包的优化
题目链接 本文旨在介绍树上背包的优化. 可见例题,例题中N,M∈[1,100000]N,M \in [1,100000]N,M∈[1,100000]的数据量让O(nm2)O(nm^2)O(nm2)的朴 ...
- HDU4044 GeoDefense(有点不一样的树上背包)
题目大概说一棵n个结点的树,每个结点都可以安装某一规格的一个塔,塔有价格和能量两个属性.现在一个敌人从1点出发但不知道他会怎么走,如果他经过一个结点的塔那他就会被塔攻击失去塔能量的HP,如果HP小于等 ...
- BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )
树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...
- luogu 2014 选课 树上背包
树上背包 #include<bits/stdc++.h> using namespace std; ; const int inf=0x3f3f3f3f; vector<int> ...
- BZOJ 4753 [Jsoi2016]最佳团体 | 树上背包 分数规划
BZOJ 4753 [Jsoi2016]最佳团体 | 树上背包 分数规划 又是一道卡精度卡得我头皮发麻的题-- 题面(--蜜汁改编版) YL大哥是24OI的大哥,有一天,他想要从\(N\)个候选人中选 ...
- 洛谷 P2015 二叉苹果树 (树上背包)
洛谷 P2015 二叉苹果树 (树上背包) 一道树形DP,本来因为是二叉,其实不需要用树上背包来干(其实即使是多叉也可以多叉转二叉),但是最近都刷树上背包的题,所以用了树上背包. 首先,定义状态\(d ...
- 【BZOJ】4033: [HAOI2015]树上染色 树上背包
[题目]#2124. 「HAOI2015」树上染色 [题意]给定n个点的带边权树,要求将k个点染成黑色,使得 [ 黑点的两两距离和+白点的两两距离和 ] 最大.n<=2000. [算法]树上背包 ...
- 【BZOJ】4753: [Jsoi2016]最佳团体 01分数规划+树上背包
[题意]n个人,每个人有价值ai和代价bi和一个依赖对象ri<i,选择 i 时 ri 也必须选择(ri=0时不依赖),求选择k个人使得Σai/Σbi最大.n<=2500,ai,bi< ...
随机推荐
- python全栈开发,Day40(进程间通信(队列和管道),进程间的数据共享Manager,进程池Pool)
昨日内容回顾 进程 multiprocess Process —— 进程 在python中创建一个进程的模块 start daemon 守护进程 join 等待子进程执行结束 锁 Lock acqui ...
- BZOJ 1096: [ZJOI2007]仓库建设 动态规划 + 斜率优化
#include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) #defi ...
- HDU6415 Rikka with Nash Equilibrium
HDU6415 Rikka with Nash Equilibrium 找规律 + 大数 由于规律会被取模破坏,所以用了java 找出规律的思路是: 对于一个n*m的矩阵构造,我先考虑n*1的构造,很 ...
- php.ini 配置项详解
本文主要对php.ini文件进行详细的解释 engine = On ——> 在apache下启用php语言引擎 short_open_tag = Off ——> 是否开启段标签 若php ...
- if isinstance(obj, int):
http://legacy.python.org/dev/peps/pep-0008/ Object type comparisons should always use isinstance() i ...
- scrapy基础笔记
公众号原文 公众号排版更友好,建议查看公众号原文 前言 reference: https://www.tutorialspoint.com/scrapy/scrapy_quick_guide.htm ...
- jmeter之断言的使用
和写功能测试用例一样,写接口测试用例也可以先可以写预期结果,然后用于后面的批量执行接口用例 目录 1.jmeter常用的断言元件 2.响应断言 3.json串断言 1.jmeter常用的断言元件 jm ...
- Js定义一个表单并提交
Js定义一个表单 var form = $("<form>"); //定义一个form表单 form.attr('style', 'display:none'); // ...
- vue全局自定义指令-元素拖拽
小白我用的是vue-cli的全家桶,在标签中加入v-drap则实现元素拖拽, 全局指令我是写在main.js中 Vue.directive('drag', { inserted: function ( ...
- MySQL 查询语句--------------进阶7:子查询
#进阶7:子查询 /* 含义: 出现在其他语句中的select语句,称为子查询或者内查询 外部的查询语句,称为主查询或外查询 分类: 按照子查询出现的位置: select后面:只支持标量子查询 fro ...