整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


Luogu P3177 [HAOI2015] 树上染色

有一棵点数为 NNN 的树,树边有边权。给你一个在 0∼N0\sim N0∼N 之内的正整数 KKK ,你要在这棵树中选择 KKK 个点,将其染成黑色,并将其他 的 N−KN-KN−K 个点染成白色 。 将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间的距离的和的受益。问受益最大值是多少。

0≤n,k≤20000≤n,k≤20000≤n,k≤2000

Solution

树上两点之间的距离即两点之间路径的长度,我们可以直接统计整棵树中每条边被计算了多少次,即对答案有多少贡献,既可求出最后的答案。

每条边被计算了几次,即被经过了几次。对于两个同色的结点,若他们在这条边的同侧,则该点对之间的路径不会经过该边。若他们在这条边的异侧,显然该点对之间的路径会经过该边一次。因此对于一条边 (x,y)(x, y)(x,y),被经过的次数 cntcntcnt,设 kkk 表示以 xxx 为根的子树中黑点的数量,mmm 表示需要选择的黑点总数量,siz[x]siz[x]siz[x] 表示以 xxx 为根的子树的总点数,则有:

cnt=k×(m−k)+(siz[x]−k)×(n−m−(siz[x]−k))\mathrm {cnt} = k\times(m - k) + (\mathrm {siz}[x]-k)\times (n-m-(\mathrm {siz}[x]-k))cnt=k×(m−k)+(siz[x]−k)×(n−m−(siz[x]−k))

由于这里并不满足最优子结构的性质,即当前子树的最大值并不一定会使得对于整棵树的答案是最大值,因此我们直接统计对整棵树的贡献,设 f[i,j]f[i, j]f[i,j] 表示在以 iii 为根的子树中,选择 jjj 个黑点对整棵树的答案的贡献。

则有转移方程

f[x,j]=max⁡{f[x,j−k]+f[y,k]+cnt×edge[x,y]}f[x,j] = \max\{f[x, j - k] + f[y, k] + \mathrm {cnt}\times \mathrm {edge}[x, y]\} f[x,j]=max{f[x,j−k]+f[y,k]+cnt×edge[x,y]}

然后就是一个树上 0/1 背包了,由于每个点只能选择一次,所以倒序枚举 jjj 。然后我们只需要考虑对于以 xxx 的子结点 yyy 为根的子树,选或者不选。

  • 若以 xxx 的子结点 yyy 为根的子树选择点将其染成黑色,通过转移方程计算即可。

  • 若以 xxx 的子结点 yyy 为根的子树不选择点将其染成黑色,则该子树对答案的贡献为子树纯白的时候对答案的贡献,计算出后,与选择以 xxx 的子结点 yyy 为根的子树中的点的情况得到的答案取 max⁡\maxmax 即可。

选或不选两种情况,所以我们的 kkk 应该枚举 0∼siz[y]0\sim \mathrm {siz}[y]0∼siz[y]。至于如何,正序倒序枚举均可。

这里有一个细节,我们的原转移方程是
f[x,j]=max⁡{f[x,j−k]+f[y,k]+cnt×edge[x,y]}f[x,j] = \max\{f[x, j - k] + f[y, k] + \mathrm {cnt}\times \mathrm {edge}[x, y]\} f[x,j]=max{f[x,j−k]+f[y,k]+cnt×edge[x,y]}

由于 n≤2000n\le 2000n≤2000,直接转移时间复杂度是 O(KN2)O(KN^2)O(KN2),最后一个点跑了 1.2s TLE了。

我们可以将转移方程改为

f[x,j+k]=max⁡{f[x,j]+f[y,k]+cnt×edge[x,y]}f[x,j+k] = \max\{f[x, j] + f[y, k] + \mathrm {cnt}\times \mathrm {edge}[x, y]\} f[x,j+k]=max{f[x,j]+f[y,k]+cnt×edge[x,y]}

先进行转移,然后再计算 siz[x] += siz[y],即从小到大递推,并保证 j+k≤mj+k\le mj+k≤m,时间复杂度是 O(N2)O(N^2)O(N2),因为对于任意两个点 x,yx,yx,y,他们只会在 lca(x,y)\mathrm{lca}(x,y)lca(x,y) 初被统计一次,所以是严格 O(n2)O(n^2)O(n2) 的。

Code

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 2e3 + 7, maxm = maxn * 2;
int n, m, s, t, ans;
ll f[maxn][maxn];
int num_white;
int siz[maxn];
int head[maxn], ver[maxm], edge[maxm], nex[maxm], tot;void add(int x, int y, int z)
{ver[tot] = y;edge[tot] = z;nex[tot] = head[x];head[x] = tot ++ ;
}void init()
{memset(head, -1, sizeof head);
}void dfs(int x, int fa)
{siz[x] = 1;ll g[maxn];memset(g, 0, sizeof g);for (int i = head[x]; ~i; i = nex[i]) {int y = ver[i], z = edge[i];if(y == fa) continue;dfs(y, x);for (int j = min(m, siz[x]); j >= 0; -- j) {for (int k = min(m, siz[y]); k >= 0; -- k) {  if(j + k > m) continue; g[j + k] = max(g[j + k], f[x][j] + f[y][k] + 1ll * z * (k * (m - k) + (siz[y] - k) * ((n - m) - (siz[y] - k))));}}siz[x] += siz[y];memcpy(f[x], g, sizeof g);}
}int main()
{init();scanf("%d%d", &n, &m);for (int i = 1; i <= n - 1; ++ i) {int x, y, z;scanf("%d%d%d", &x, &y, &z);add(x, y, z);add(y, x, z);}dfs(1, 0);cout << f[1][m] << endl;return 0;}

Luogu P3177 [HAOI2015] 树上染色(树上背包)相关推荐

  1. [BZOJ4033][HAOI2015]树上染色(树形DP)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2437  Solved: 1034 [Submit][St ...

  2. bzoj4033: [HAOI2015]树上染色(树形dp)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 3269  Solved: 1413 [Submit][St ...

  3. [BZOJ4033][HAOI2015]树上染色

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2108  Solved: 901 [Submit][Sta ...

  4. 【HAOI2015】树上染色

    [HAOI2015]树上染色 这题思路好神仙啊,首先显然是树形dp,f[i][j]表示在以i为根的子树中选j个黑点对答案的贡献(并不是当前子树最大值),dp时只考虑i与儿子连边的贡献.此时(i,son ...

  5. bzoj 4033: [HAOI2015]树上染色(树形DP)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 1786  Solved: 754 [Submit][Sta ...

  6. 最简单的树上染色问题(没有之一)

    感觉最近做题都做傻了,这道题居然没有任何思路,(去世摸鱼中) 种植花圃 题目描述 众所周知,蔡老板有一个巨大的庄园.蔡老板已经厌倦了庄园现有的花圃颜色,决定重新对庄园重新种植花圃.为了简化这个问题,我 ...

  7. 洛谷 P3177 [HAOI2015]树上染色

    题目链接 题目描述 有一棵点数为 \(N\) 的树,树边有边权.给你一个在 \(0~ N\) 之内的正整数 \(K\) ,你要在这棵树中选择 \(K\)个点,将其染成黑色,并将其他 的\(N-K\)个 ...

  8. [HAOI2015]树上染色(树形dp,树形背包)

    链接:https://ac.nowcoder.com/acm/problem/19996 来源:牛客网 题目描述 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个 ...

  9. [HAOI2015]树上染色(树形背包)

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

最新文章

  1. 移动端实现PDF文件阅读的方法
  2. video.min.js php,使用flv.js与video.js做一个视频直播效果
  3. 如何删除Safari浏览器的扩展程序 大神教你搞定
  4. Android Service学习之本地服务
  5. php oauth api,PHP实现人人OAuth登录和API调用
  6. 【黑马程序员 C++教程从0到1入门编程】【笔记2】通讯录管理系统
  7. c语言编译机器码,[转载]单片机C语言到机器码的全过程
  8. 利用loadrunner做性能测试过程中遇到的问题
  9. matlab用solve解方程错误提示,MATLAB中使用solve解决方程组的问题
  10. 精通 Pandas · 翻译完成
  11. iOS 设计中 网络请求之 同步请求(json 请求--新方法和老方法)
  12. Codeforces.888G.Xor-MST(Borůvka算法求MST 贪心 Trie)
  13. Linux---进程的基本概念
  14. 我33岁,从国企主管零基础转型大数据开发,年薪涨了20W
  15. Leetcode 最小栈问题
  16. 让VMware ESXi 5.5与Windows时间服务器同步
  17. 深度学习简单线性训练
  18. raid5两块硬盘掉线数据恢复-服务器磁盘阵列数据恢复方法
  19. mac使用cjk和ctex宏包
  20. 红米停在android,红米手机在Android开发中无法获取data/data中数据的问题

热门文章

  1. 来啦!机器学习画图神器来啦!
  2. 熬了几个大夜,学完一套985博士总结的OpenCV学习笔记(20G高清/PPT/代码)
  3. SPI flash配置
  4. jeecg富文本编辑器增加字体(仿宋)
  5. 一步一步粗谈linux文件系统(三)----超级块(superblock)【转】
  6. Django快速开发之投票系统
  7. LC124 Binary Tree Maximum Path Sum
  8. SharePoint 2013 处理videoplayerpage.aspx下的个人图片显示有误问题
  9. HTML5 Geolocation
  10. SUN Zone Cluster安装及配置说明之三