ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

树上染色

2021-07-31 21:00:44  阅读:205  来源: 互联网

标签:include int 染色 个数 1LL 为根 siz 树上


题面

树上染色

题解

这道题转移应该很容易。
直接枚举当前节点染黑的个数以及子节点染黑的个数即可。
设 \(f[x][j]\) 表示以 \(x\) 为根节点的子树中染黑 \(j\) 个点时两种颜色两两距离的之和的最大值。
所以有状态转移方程:

\[f[x][j] = min(f[x][j - p] + f[y][p] + val) \]

其中 \(p\) 为以 \(y\) 为根的子树中染黑的个数, \(y\) 是 \(x\) 的子节点。
后面的 \(val\) 表示连通 \(x,y\) 之后新增的距离。
显然增加的距离是由某种颜色在以 \(y\) 为根的子树中,和其子树外的这种颜色产生的。
我们把两个点之间的路径拆成边,那么总答案就是每条边的长度乘上经过次数的和,所以我们可以倒过来把总答案拆成这样,那么 \(val\) 就等于 \(x, y\) 之间的边的长度乘上它被黑点两两经过和白点两两经过的次数和。
而根据乘法原理对于单种颜色,这条边被这种颜色两两经过的次数就是以 \(y\) 为根的子树中这种颜色的个数乘上子树外的颜色个数。

\[val = (1LL * p * (k - p) + 1LL * (siz[y] - p) * (n - k - siz[y] + p)) * w; \]

\(p\) 的定义和上述的一样,\(k\) 是黑色的总个数,\(w\) 是 \(x,y\) 之间的边的长度,\(siz\) 是子树的大小。
当 \(k\) 大于 \(n\) 的一半时,我们可以把状态改为染白,这两种是等效的。
然而复杂度上限是 \(2e9\),虽然因为子树大小的原因达不到这个上界,但还是可能会被卡,虽然在洛谷上能过,但据说在 BZOJ 上会被卡爆。

代码

#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

typedef long long LL;

const int N = 2e3 + 5;

int n, k, siz[N]; LL f[N][N]; 

vector < pair < int, int > > to[N];

inline void add(int u, int v, int w) { to[u].push_back(make_pair(v, w)); to[v].push_back(make_pair(u, w)); }

void dfs(int x, int fa) {
	siz[x] = 1; f[x][0] = f[x][1] = 0;
	for(unsigned int i = 0; i < to[x].size(); i++) {
		int y = to[x][i].first, w = to[x][i].second;
		if(y == fa) continue;
		dfs(y, x); siz[x] += siz[y];
		for(int j = min(k, siz[x]); ~j; j--) {
			if(f[x][j] != -1)
				f[x][j] = f[x][j] + f[y][0] + 1LL * siz[y] * (n - k - siz[y]) * w;
			for(int p = min(j, siz[y]); p; p--) {
				if(f[x][j - p] == -1) continue;
				LL tmp = (1LL * p * (k - p) + 1LL * (siz[y] - p) * (n - k - siz[y] + p)) * w;
				f[x][j] = max(f[x][j], f[x][j - p] + f[y][p] + tmp);
			}
		}
	}
}

int main() {
	scanf("%d%d", &n, &k);
	if(n < (k << 1)) k = n - k;
	for(int i = 1, u, v, w; i < n; i++) scanf("%d%d%d", &u, &v, &w), add(u, v, w);
	memset(f, -1, sizeof f);
	dfs(1, 0);
	printf("%lld\n", f[1][k]);
	return 0;
}

标签:include,int,染色,个数,1LL,为根,siz,树上
来源: https://www.cnblogs.com/sjzyh/p/15085224.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有