| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> BZOJ 2133 切割(树形DP,树上背包)大概是本题全网第一篇题解 >_<【BZOJ 修复工程】 -> 正文阅读 |
|
[数据结构与算法]BZOJ 2133 切割(树形DP,树上背包)大概是本题全网第一篇题解 >_<【BZOJ 修复工程】 |
整理的算法模板合集: ACM模板
BZOJ 2133 切割这道题全网搜不到任何一篇题解 >_< 看评测记录也没有几个人AC… 不过其实很简单就是了,可能是大佬们写完之后不屑于写题解吧 o(〃^▽^〃)o 题目链接https://hydro.ac/d/bzoj/p/2133 是 hydro 的 BZOJ 修复工程 !(我也去领了一点题慢慢修着玩,这题就是我修的嘿嘿嘿) 题目描述有一棵 n n n 个节点的无根树,节点编号为 1 … n 1\dots n 1…n。每个节点有一个非负权值。现在需要把这棵树分成若干个联通块(不能有剩下的点),每个联通块的节点个数在 k 1 k_1 k1? 和 k 2 k_2 k2? 之间,每个联通块的得分就是该联通块中所有节点权值的平均值。总得分就是指对这个树切割后所有联通块的得分的和。你需要求出一种分割的方案使得总得分尽量小。 输入格式第一行三个整数 n , k 1 , k 2 n,k_1,k_2 n,k1?,k2?; 第二行 n n n 个整数,第 i i i 个数表示编号为 i i i 的节点的权值,每两个相邻整数之间用一个空格隔开; 接下来 n ? 1 n-1 n?1 行,每行两个整数 x , y x,y x,y ,表示编号为 x x x的节点和编号为 y y y的节点之间有一条边。 输出格式如果存在一个切割方案,那么输出一个实数(四舍五入保留二位小数),表示所有分割方案中最小的总得分。如果不存在切割方案,那么输出所有节点权值和的两倍。如果对于某个测试点你的输出和标准输出完全一样,那么将得到该测试点全部的分,否则该测试点不得分(我写的sp貌似有问题,大家可以使用 输入样例
输出样例
数据规模与约定对于 100 % 100\% 100% 的数据, 1 ≤ k 1 ≤ k 2 ≤ n , 2 ≤ n ≤ 50 1\le k_1\le k_2\le n,2\le n\le 50 1≤k1?≤k2?≤n,2≤n≤50,每个点的权值均不超过 1 0 9 10^9 109 。 Solution 首先随便定一个点 r o o t root root 为树根,将无根树转化为有根树。 数据较大,显然不可能直接爆搜,考虑树形DP。 显然设 f [ i ] f[i] f[i] 表示以 i i i 为根的子树中能获得的最小的总得分,分析题意考虑需要维护哪些信息。 首先题目中给定的计算方式暂时没有什么切入点,先忽略掉,对于每个连通块,块内结点个数是有一个范围限制的,即 k 1 ≤ n u m ≤ k 2 k_1\le num\le k_2 k1?≤num≤k2?,显然我们需要维护这个信息,考虑设 f [ i , j ] f[i,j] f[i,j] 表示以 i i i 为根的子树在切割后,所属的连通块的结点个数为 j j j ,能获得的最小总得分。 发现没法转移… 考虑 n ≤ 50 n\le 50 n≤50, O ( n 4 ) ~ O ( n 4 log ? n ) O(n^4)\sim O(n^4\log n) O(n4)~O(n4logn),甚至 O ( n 5 ) O(n^5) O(n5) 都有可能通过(手动狗头) 考虑再增加一些维护的信息。 树形DP考虑从子树的角度出发分析,题目可以转换为从子树中选择若干个点,加入到根节点的连通块内,即树上背包问题,考虑转移和需要维护的信息。显然我们只能从子树中选取不超过该连通块的总数 j j j 的节点数放入当前连通块内,考虑维护 k k k 表示根节点 i i i 的子树中被选入 i i i 所在的连通块的结点个数,这样我们将问题转化为一个 0/1 背包的模型,直接按照背包 O ( n 2 ) O(n^2) O(n2) 转移即可。 即设 f [ i , j , k ] f[i,j,k] f[i,j,k] 表示以 i i i 为根的 子树 在切割后,结点 i i i 所属的连通块的结点个数为 j j j ,子树中被选入 i i i 所在的连通块的结点个数为 k k k (显然包括),能获得的最小的总得分。 考虑如何维护答案,因为我们并不能确定每个连通块内结点的个数,因此我们直接以 i i i 为根维护答案即可,设 a n s [ i ] ans[i] ans[i] 表示以 i i i 为根的 子树中 的最小总得分,显然我们必须要从子树中选择 j j j 个结点填满背包才算合法,故答案为: a n s [ i ] = min ? { f [ i ] [ j ] [ j ] ∣ j ∈ [ k 1 , k 2 ] } \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?]} 最后的答案显然是 a n s [ r o o t ] ans[root] ans[root]。 最后如果没有合法的方案的话( 注意 Code
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/30 1:08:23- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |