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

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

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


BZOJ 2133 切割这道题全网搜不到任何一篇题解 >_<

看评测记录也没有几个人AC…

不过其实很简单就是了,可能是大佬们写完之后不屑于写题解吧 o(〃^▽^〃)o


题目链接

https://hydro.ac/d/bzoj/p/2133

是 hydro 的 BZOJ 修复工程 !(我也去领了一点题慢慢修着玩,这题就是我修的嘿嘿嘿)

题目描述

有一棵 nnn 个节点的无根树,节点编号为 1…n1\dots n1…n。每个节点有一个非负权值。现在需要把这棵树分成若干个联通块(不能有剩下的点),每个联通块的节点个数在 k1k_1k1​ 和 k2k_2k2​ 之间,每个联通块的得分就是该联通块中所有节点权值的平均值。总得分就是指对这个树切割后所有联通块的得分的和。你需要求出一种分割的方案使得总得分尽量小。

输入格式

第一行三个整数 n,k1,k2n,k_1,k_2n,k1​,k2​;

第二行 nnn 个整数,第 iii 个数表示编号为 iii 的节点的权值,每两个相邻整数之间用一个空格隔开;

接下来 n−1n-1n−1 行,每行两个整数 x,yx,yx,y ,表示编号为 xxx的节点和编号为 yyy的节点之间有一条边。

输出格式

如果存在一个切割方案,那么输出一个实数(四舍五入保留二位小数),表示所有分割方案中最小的总得分。如果不存在切割方案,那么输出所有节点权值和的两倍。如果对于某个测试点你的输出和标准输出完全一样,那么将得到该测试点全部的分,否则该测试点不得分(我写的sp貌似有问题,大家可以使用 double 类型存储数据,输出结果的整数部分保证不超过 999 位(十进制),使用 double 类型可以保证小数部分至少是 666位,因而精度应该不存在问题)。

输入样例

3 1 1
1 1 1
1 2
2 3

输出样例

3.00

数据规模与约定

对于 100%100\%100% 的数据,1≤k1≤k2≤n,2≤n≤501\le k_1\le k_2\le n,2\le n\le 501≤k1​≤k2​≤n,2≤n≤50,每个点的权值均不超过 10910^9109 。

Solution

首先随便定一个点 rootrootroot 为树根,将无根树转化为有根树。

数据较大,显然不可能直接爆搜,考虑树形DP。

显然设 f[i]f[i]f[i] 表示以 iii 为根的子树中能获得的最小的总得分,分析题意考虑需要维护哪些信息。

首先题目中给定的计算方式暂时没有什么切入点,先忽略掉,对于每个连通块,块内结点个数是有一个范围限制的,即 k1≤num≤k2k_1\le num\le k_2k1​≤num≤k2​,显然我们需要维护这个信息,考虑设 f[i,j]f[i,j]f[i,j] 表示以 iii 为根的子树在切割后,所属的连通块的结点个数为 jjj ,能获得的最小总得分。

发现没法转移…

考虑 n≤50n\le 50n≤50,O(n4)∼O(n4log⁡n)O(n^4)\sim O(n^4\log n)O(n4)∼O(n4logn),甚至 O(n5)O(n^5)O(n5) 都有可能通过(手动狗头)

考虑再增加一些维护的信息。

树形DP考虑从子树的角度出发分析,题目可以转换为从子树中选择若干个点,加入到根节点的连通块内,即树上背包问题,考虑转移和需要维护的信息。显然我们只能从子树中选取不超过该连通块的总数 jjj 的节点数放入当前连通块内,考虑维护 kkk 表示根节点 iii 的子树中被选入 iii 所在的连通块的结点个数,这样我们将问题转化为一个 0/1 背包的模型,直接按照背包 O(n2)O(n^2)O(n2) 转移即可。

即设 f[i,j,k]f[i,j,k]f[i,j,k] 表示以 iii 为根的 子树 在切割后,结点 iii 所属的连通块的结点个数为 jjj ,子树中被选入 iii 所在的连通块的结点个数为 kkk (显然包括),能获得的最小的总得分。

考虑如何维护答案,因为我们并不能确定每个连通块内结点的个数,因此我们直接以 iii 为根维护答案即可,设 ans[i]ans[i]ans[i] 表示以 iii 为根的 子树中 的最小总得分,显然我们必须要从子树中选择 jjj 个结点填满背包才算合法,故答案为:ans[i]=min⁡{f[i][j][j]∣j∈[k1,k2]}\displaystyle ans[i] = \min\{f[i][j][j]\mid j\in[k_1,k_2]\}ans[i]=min{f[i][j][j]∣j∈[k1​,k2​]}

最后的答案显然是 ans[root]ans[root]ans[root]。

最后如果没有合法的方案的话(ans[root] == maxx),根据题意输出总和的二倍即可。

注意 double 类型的数使用 memset 初始化的时候,∞\infin∞ 使用 0x7f,−∞-\infin−∞ 使用 0xef

Code

#include <bits/stdc++.h>
using namespace std;const int maxn = 100 + 7, maxm = maxn << 1, INF = 0x3f3f3f3f;
const double DINF = 1e18, eps = 1e-8;
int n, m, s, t;
int k1, k2;
double w[maxn];
double f[maxn][maxn][maxn];
double ans[maxn];
int siz[maxn];
vector <int> e[maxn];
bool vis[maxn];
double sum;int sgn(double x)
{if(fabs(x) < eps)return 0;if(x < 0)return -1;return 1;
}void dfs(int x, int fa)
{ for (auto y : e[x]) {if(y == fa) continue;dfs(y, x); } for (int j = k1; j <= k2; ++ j) {f[x][j][1] = w[x] / j;for (auto y : e[x]) {if(y == fa) continue;for (int k = j; k >= 1; -- k) {f[x][j][k] = f[x][j][k] + ans[y];for (int l = 1; l <= k - 1; ++ l) if(sgn(f[x][j][k] - (f[x][j][k - l] + f[y][j][l])) == 1)f[x][j][k] = f[x][j][k - l] + f[y][j][l];}}if(sgn(ans[x] - f[x][j][j]) == 1)ans[x] = f[x][j][j];}
}int main()
{ sum = 0;memset(f, 0x7f, sizeof f);memset(ans, 0x7f, sizeof ans);double maxx = ans[1];scanf("%d%d%d", &n, &k1, &k2);for (int i = 1; i <= n; ++ i) scanf("%lf", &w[i]), sum += w[i];for (int i = 1; i <= n - 1; ++ i) {int x, y;scanf("%d%d", &x, &y);e[x].push_back(y);e[y].push_back(x);}dfs(1, -1);if(ans[1] == maxx) printf("%.2f", sum * 2.0);else printf("%.2f", ans[1]);return 0;
}

BZOJ 2133 切割(树形DP,树上背包)大概是本题全网第一篇题解 >_<【BZOJ 修复工程】相关推荐

  1. bzoj 1369: Gem 树形dp

    题目大意 给出一棵树,要求你为树上的结点标上权值,权值可以是任意的正整数 唯一的限制条件是相临的两个结点不能标上相同的权值,要求一种方案,使得整棵树的总价值最小.N<=10000 题解 我们可以 ...

  2. cf 1060e 树形dp 树上任意两点的距离和

    题意: 给出一个树,把树上任意两个相隔一个点的点加一条边,问加完边之后任意两点的距离和是多少.   参考博客 :https://blog.csdn.net/Mr_Treeeee/article/det ...

  3. HYSBZ - 1017 魔兽地图【树形DP依赖性背包】

    HYSBZ - 1017 Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defen ...

  4. BZOJ 2651 城市改建 树形DP+模拟?

    题意 给一颗树,删除一条边再加一条边,使它仍为一颗树且任意两点间的距离的最大值最小. 题目数据范围描述有问题,n为1或重建不能使任意两点距离最大值变小,可以输出任意答案. 分析 删除一条边后会使它变成 ...

  5. hdu5148 树形dp,分组背包

    dp[i][j]表示以i为根节点的子树中选j个城市贡献边长的最小值,怎样由子树向上递推呢,子树是一个天然的组,dp[u][j]可以这样理解,u子树容量为j是由上一层dp[u][j-f]推出的,应用了滚 ...

  6. BZOJ 4753 二分+树形DP

    思路: 先二分答案 f[x][j]表示在x的子树里选j个点 f[x][j+k]=max(f[x][j+k],f[x][j]+f[v[i]][k]); 初始化 x!=0 -> f[x][1]=p[ ...

  7. 树形dp+树形结构总结

    总结 最近写了好多树形dp+树形结构的题目,这些题目变化多样能与多种算法结合,但还是有好多规律可以找的. 先说总的规律吧! 一般来说树形dp在设状态转移方程时都可以用f[i][]表示i这颗子树怎么怎么 ...

  8. PAT甲级1106 Lowest Price in Supply Chain:[C++题解]树、结点到根结点的距离、树形dp、记忆化搜索

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析:这道题是第三次做了. 和PAT甲级1079 Total Sales of Supply Chain:[C++题解] 树.结点到根结点的 ...

  9. PAT甲级1090 Highest Price in Supply Chain:[C++题解]树、结点到根结点的距离、记忆化搜索、树形dp

    文章目录 题目分析 题目链接 题目分析 来源:acwing 和PAT甲级1079 Total Sales of Supply Chain:[C++题解] 树.结点到根结点的距离.树形dp.记忆化搜索是 ...

最新文章

  1. Zookeeper的安装配置及基本开发
  2. office2016word 每次打开都有进度条问题 解决方式
  3. java中对集合排序,Java如何对集合中的项目排序?
  4. 换64位Win7了,感觉还行
  5. 通过反射获取无参构造方法并使用
  6. Beego 学习笔记9:Boostrap使用介绍
  7. (进阶篇)Redis6.2.0 集群 哨兵模式_故障转移_03
  8. 机动车c1科三考试语言灯光,c1科目三灯光模拟考试
  9. 毕设日志——Fast RCNN
  10. 车辆贷款违约预测 Top1(2021科大讯飞)
  11. 艺术字体图标设计软件Art Text 4 for Mac
  12. 利用jsonp跨域访问
  13. 市盈率、市净率、净资产收益率股息率介绍
  14. ethtool 开启网卡_技术|如何使用 ethtool 命令管理以太网卡
  15. HotDB——布式事务数据库中不同数据库表对象的类型设计准测
  16. S7-1200PLC定时器计数器的应用
  17. Python微信操控itchat定时发送消息
  18. 语音信号调制matlab,第二章 语音信号的数字模型 数字语音处理及MATLAB仿真 教学课件.ppt...
  19. 海明校验码算法和纠错
  20. vivo X90和iPhone 14哪个好 vivo X90 和苹果14 区别对比评测

热门文章

  1. 迁移学习:领域自适应的理论分析
  2. 从数据集到2D和3D方法,一文概览目标检测领域进展
  3. CAPSNET:具有自我注意路由的胶囊网络
  4. 1、交换机ARP缓存表分析
  5. 青桔单车 chameleon 跨平台实践
  6. Scala编程之闭包(closure)
  7. iOS 项目集成Flutter
  8. 聊聊《柒个我》这部剧
  9. VIEW层AJAX提交表单到Controller的实体(AJAX传递序列化的输入元素)
  10. 编程十年的十种武学境界