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

Posted 繁凡さん

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 1n。每个节点有一个非负权值。现在需要把这棵树分成若干个联通块(不能有剩下的点),每个联通块的节点个数在 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 n1 行,每行两个整数 x , y x,y x,y ,表示编号为 x x x的节点和编号为 y y y的节点之间有一条边。

输出格式

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

输入样例

3 1 1
1 1 1
1 2
2 3

输出样例

3.00 

数据规模与约定

对于 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 1k1k2n2n50,每个点的权值均不超过 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 k1numk2,显然我们需要维护这个信息,考虑设 f [ i , j ] f[i,j] f[i,j] 表示以 i i i 为根的子树在切割后,所属的连通块的结点个数为 j j j ,能获得的最小总得分。

发现没法转移…

考虑 n ≤ 50 n\\le 50 n50 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]

最后如果没有合法的方案的话(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 修复工程的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2427: [HAOI2010]软件安装tarjan+树形dp

[填坑][支线任务]树形DP 树形背包

bzoj4753: [Jsoi2016]最佳团体(分数规划+树形依赖背包)

BZOJ.3257.树的难题(树形DP)

动态规划-树形DP-树上背包专题

树形背包bzoj4033: [HAOI2015]树上染色