这两道题是学长精心准备的,想了很长时间,比较经典。

第一题 树上染色

有一棵点数为 N的树,树边有边权。给你一个在 0∼N之内的正整数 K,你要在这棵树中选择 K 个点,将其染成黑色,并将其他的 N−K个点染成白色。将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间距离的和的收益。

问收益最大值是多少。

这一题一开始没思路主要是卡在了在从下向上转移中,如何将每个儿子的贡献值的算上

后来怂了题解QAQ

这题是树状背包问题

主要难点在于如何将每条边数加上,

设当前的节点为x而儿子节点为to

那么我们可以发现当前数组f[x][j]中包含的是x之前的儿子所做的贡献

这是树状背包常考虑的事情那么我们为了求当前的to所做的贡献

只需考虑当前to与x之间的边所做的贡献

(至于证明,显然此时f[x][j+k]=max(f[x][j+k],f[x][j]+f[to][k]+........)中f[x][j]是已转移过的,而此时需要将新加子树算进,这样枚举完x的子树后就是正确的。)

 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <string>
5 #include <cmath>
6 #include <queue>
7 #include <stack>
8 #include <vector>
9 #define MAXN 5001
10 #define pt printf("-----------\n");
11 #define push_back ps
12 #define ll long long
13 using namespace std;
14 struct node {
15 ll to, n, w;
16 } e[MAXN];
17 ll head[MAXN], tot;
18 void add(ll u, ll v, ll w) {
19 e[++tot].to = v;
20 e[tot].n = head[u];
21 e[tot].w = w;
22 head[u] = tot;
23 }
24 ll f[MAXN][MAXN];
25 ll size[MAXN];
26 ll n, K;
27 bool bian[MAXN];
28 void DFS(ll x) {
29 bian[x] = 1;
30 size[x] = 1;
31 f[x][0]=f[x][1]=0;
32 for (ll i = head[x]; i; i = e[i].n) {
33 ll to = e[i].to;
34 if (bian[to] == 1)
35 continue;
36 bian[to] = 1;
37 DFS(to);
38 size[x] += size[to];
39 for (ll j = min(K, size[x]); j >= 0; --j) {
40 for (ll k = 0; k <= j; ++k) {
41 if (k > size[to])
42 break;
43 f[x][j] =
44 max(f[x][j], f[x][j - k] + f[to][k] +
45 e[i].w * (k * (K - k) + (size[to] - k) * (n - K - (size[to] - k))));
46 // printf("size[%lld]=%lld size[%lld]=%lld 黑zi=%lld 黑qi=%lld 白zi=%lld
47 // 白qi=%lld\n",to,size[to],x,size[x],k,K-k,size[to]-k,n-K-(size[to]-k));
48 // printf("---f[%lld][%lld]=%lld f[%lld][%lld]=%lld\n",x,j-k,f[x][j-k],to,k,f[to][k]);
49 }
50 // printf("f[%lld][%lld]=%lld\n",x,j,f[x][j]);
51 }
52 }
53 }
54 ll root = 1;
55 ll ru[MAXN];
56 int main() {
57 memset(f,-0x3f,sizeof(f));
58 scanf("%lld%lld", &n, &K);
59 for (ll i = 1; i <= n - 1; ++i) {
60 ll x, y, w;
61 scanf("%lld%lld%lld", &x, &y, &w);
62 add(x, y, w);
63 add(y, x, w);
64 }
65 // DFS_S(root);
66 memset(bian, 0, sizeof(bian));
67 DFS(root);
68 ll ans = 0;
69 ans = max(ans, f[root][K]);
70 printf("%lld\n", ans);
71 }

第二题

一道不错的树状DP

有几个限制条件n个物品,各有价值,各有优惠券,除一外都有一个使用的条件,问钱b买多少商品。

这题我们不直接求结果,用f[x][y][2],表示第x点买y个物品的最小值,1表示用券,0则反。

那么最后一位是1时比较好处理

因为x必选,所以f[x][j+k][1]=min(f[x][j+k][1],f[x][j][1]+min(f[to][k][1],f[to][k][0]);

可以提前给f[x][1][1]加上c[x]-d[x],这样转移方程中就不会加重。

而为0时,f[x][j+k][0]=min(f[x][j+k][0],f[x][j][0]+f[to][k][0])

因为x可能选

最后再用for从1~size[x]用f[x][i-1]+c[i]更新f[x][i]最小值

 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<string>
5 #include<algorithm>
6 #include<cmath>
7 using namespace std;
8 #define MAXN 6000
9 int head[MAXN],tot;struct node{int to,n;}e[MAXN];
10 void add(int u,int v){e[++tot].to=v;e[tot].n=head[u];head[u]=tot;}
11 int f[MAXN][MAXN][2];int n,c[MAXN],d[MAXN];
12 int deep=1;
13 int size[MAXN];
14 void DFS(int x)
15 {
16 size[x]=1;
17 f[x][1][1]=c[x]-d[x];f[x][0][0]=0;
18 for(int i=head[x];i;i=e[i].n)
19 {
20 int to=e[i].to;
21 DFS(to);
22 // printf("---------%d\n",to);
23 // printf("deep=%d\n",deep);
24 for(int j=size[x];j>=0;--j)
25 {
26 for(int k=size[to];k>=0;--k)
27 {
28 f[x][j+k][1]=min(f[x][j+k][1],f[x][j][1]+min(f[to][k][1],f[to][k][0]));
29 f[x][j+k][0]=min(f[x][j+k][0],f[x][j][0]+f[to][k][0]);
30 // printf("f[%d][%d][1]=%d f[%d][%d][0]=%d\n",x,j,f[x][j+k][1],x,j,f[x][j+k][0]);
31 }
32 }
33 size[x]+=size[to];
34 }
35 for(int i=size[x];i>=1;--i)
36 {
37 f[x][i][0]=min(f[x][i][0],f[x][i-1][0]+c[x]);
38 }
39 }
40 int b;
41 int main()
42 {
43 scanf("%d%d",&n,&b);
44 memset(f,0x3f,sizeof(f));
45 for(int i=1;i<=n;++i)
46 {
47 int x;
48 if(i==1)
49 scanf("%d%d",&c[i],&d[i]);
50 else
51 {
52 scanf("%d%d%d",&c[i],&d[i],&x);
53 add(x,i);
54 }
55 f[i][1][1]=c[i]-d[i];
56 }
57 int root=1;
58 DFS(root);
59 int x;
60 for(x=1;x<=n;++x)
61 {
62 if(f[1][x][1]>b&&f[1][x][0]>b)break;
63 }
64 printf("%d\n",x-1);
65 }

树状DP注意点:

1.首先树状DP大部分情况都是逆推,用根节点统计答案。

2.在做树状背包时一定要注意不能单纯用f[to]更新f[x],因为这样枚举不全,只考虑了一棵子树

所以一般两层循环枚举第二维来更新

3注意倒序,不要重复更新。

最后感谢kx解决我做题的傻逼错误。

树上染色+可怜与超市(树状DP)的更多相关文章

  1. poj3659树状DP

    Cell Phone Network Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6273   Accepted: 225 ...

  2. [Codeforces743D][luogu CF743D]Chloe and pleasant prizes[树状DP入门][毒瘤数据]

    这个题的数据真的很毒瘤,身为一个交了8遍的蒟蒻的呐喊(嘤嘤嘤) 个人认为作为一个树状DP的入门题十分合适,同时建议做完这个题之后再去做一下这个题 选课 同时在这里挂一个选取节点型树形DP的状态转移方程 ...

  3. 树状DP (poj 2342)

    题目:Anniversary party 题意:给出N各节点的快乐指数,以及父子关系,求最大快乐指数和(没人职员愿意跟直接上司一起玩): 思路:从底向上的树状DP: 第一种情况:第i个员工不参与,F[ ...

  4. POJ3659 Cell Phone Network(树上最小支配集:树型DP)

    题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. ...

  5. hdu 1561 The more, The Better_树状dp

    题目链接 题意:给你一棵树,各个节点都有价值(除根节点),从根节点出发,选择m个节点,问最多的价值是多小. 思路:很明显是树状dp,遍历树时背包最优价值,dp[i][k]=max{dp[i][r]+d ...

  6. poj 2342 Anniversary party_经典树状dp

    题意:Ural大学有n个职员,1~N编号,他们有从属关系,就是说他们关系就像一棵树,父节点就是子节点的直接上司,每个职员有一个快乐指数,现在要开会,职员和职员的直接上司不能同时开会,问怎才能使开会的快 ...

  7. 树状DP HDU1520 Anniversary party

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 题意:职员之间有上下级关系,每个职员有自己的happy值,越高在派对上就越能炒热气氛.但是必须是 ...

  8. HDU 4714 Tree2cycle(树状DP)(2013 ACM/ICPC Asia Regional Online ―― Warmup)

    Description A tree with N nodes and N-1 edges is given. To connect or disconnect one edge, we need 1 ...

  9. poj2486--Apple Tree(树状dp)

    Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7789   Accepted: 2606 Descri ...

随机推荐

  1. 接口测试原理及Postman详解

    接口测试定义 接口是前后端沟通的桥梁,是数据传输的通道,包括外部接口.内部接口.内部接口又包括:上层服务与下层服务接口,同级接口 生活中常见接口:电脑上的键盘.USB接口,电梯按钮,KFC下单 接口测 ...

  2. OJ最大值最小化问题(分发书本)

    该类问题通用描述: 有n个物体,每个物体都有一个权值V[i],现在将n个物体连续分成m个部分,m个部分有一个部分会拿到最多的权值v.求所有分配方式中最小的v. 典型题目: 分发书本,宠物屋涂色等. 问 ...

  3. 如何使用flask将模型部署为服务

    在某些场景下,我们需要将机器学习或者深度学习模型部署为服务给其它地方调用,本文接下来就讲解使用python的flask部署服务的基本过程. 1. 加载保存好的模型 为了方便起见,这里我们就使用简单的分 ...

  4. Spring的安装

    Spring的安装 Spring框架包 spring-framework-4.3.6RELEASE-dist.zip http://repo.spring.io/simple/libs-release ...

  5. 老J的技术分享之总结

    老J做IT这块有二十多个年头了,算是中国IT的见证者与参与者.那个时候刚开始接触和了解时,对于他的一些建议,我不是很乐于去接受,因为我觉得他的那一套技术体系不是很适合如今的情况,当时间久了后发现,他对 ...

  6. queryset惰性与缓存

    https://blog.csdn.net/zhu6201976/article/details/83550461

  7. [bug] 前台表单添加数据,后台返回成功消息,但数据库相应字段值为null

    原因 前端代码中输入框字段值和后端定义的属性值不一致 分析 bean . controller 如下图,浏览器收到后台返回消息,在后台也可打印user信息,说明已成功接收前端JSON数据并转换为use ...

  8. [DB] SQL 必知必会

    整体架构 数据类型 文本类:CHAR.VARCHAR(可变长度字符,多使用).TEXT.LONGTEXT(文本较大时使用) 数字类:TINYINT.INT.BIGINT.FLOAT.DOUBLE 日期 ...

  9. Shell $?获取函数返回值或者上一个命令的退出状态

    Shell $?获取函数返回值或者上一个命令的退出状态 来自:互联网 时间:2021-01-12 阅读:2 $? 是一个特殊变量,用来获取上一个命令的退出状态,或者上一个函数的返回值. 所谓退出状态, ...

  10. centos 6 x64 yum(sohu)

    centos 6 x64 yum(sohu) weixin_34405354 2012-08-23 10:07:35 24 收藏 文章标签: 运维 版权 [base] name=Base baseur ...