[HAOI2015][bzoj 4033]树上染色(树dp+复杂度分析)
【题目描述】
有一棵点数为N的树,树边有边权。给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色。将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间距离的和的收益。问收益最大值是多少。
【输入格式】
第一行两个整数N,K。
接下来N-1行每行三个正整数fr,to,dis,表示该树中存在一条长度为dis的边(fr,to)。输入保证所有点之间是联通的。
【输出格式】
输出一个正整数,表示收益的最大值。
【输入样例1】
3 1
1 2 1
1 3 2
【输出样例1】
3
【输入样例2】
5 2
1 2 3
1 5 1
2 3 1
2 4 2
【输出样例2】
17
【样例解释】
在第二个样例中,将点1,2染黑就能获得最大收益。
【数据范围】
对于30%的数据,N<=20
对于50%的数据,N<=100
对于100%的数据,N<=2000,0<=K<=N。
题解
很显然是个树dp,然后问题来了,怎么设计状态,根据经验我们可以设计出$dp[i][j]$表示以$i$为根的子树中染了$j$个黑点的贡献,但是这里所说的贡献是对整体还是只考虑局部呢,答案是对整体的贡献,因为很显然这个题目中满足局部最优并不一定就满足整体最优,这样状态定义就结束了,我们在来考虑转移,我们设当前枚举的根节点为$x$,我们再来枚举他的子节点$y$,发现无法直接通过子节点转移到父节点,我们再考虑,是什么连接子节点和父节点,是边,那我们就可以通过边的贡献来转移,那么每条边的贡献就是边权×子树中黑点数×子树外黑点数+边权×子树中白点数×子树外白点数。这样就可以愉快的转移了
$dp[x][j+m]=\max{(dp[y][m]+dp[x][j]+val)}$
其中j枚举x子树大小,m枚举y子树大小,val就是边的贡献。
然后就是要倒着枚举(其实正着枚举也行,就是麻烦),因为如果单纯的正着枚举,会导致用更新过的来更新,而不是正常的转移,即你要用之前的子树大小和当前子树来更新父节点,但如果不做任何处理的正着枚举就会导致用已经更新到size的值来更新,就会不对。
还有就是转移要放到dfs循环里边,其实和上面一样,就是你只是用前面的size,而不是总的size,具体看代码里的注释吧
还有要注意的一点就是因为这题你把所有黑点和白点互换不会对答案产生影响,所以$k=\min{(k,n-k)}$。
一遍dfs即可。
这样做的复杂度时$O(n^2)$的,简单点说就是因为每个点最多只会和其他点乘一次。
#include<cstdio>
using namespace std;
const int N=,M=,L=<<|;
//#define int long long
#define rg register int
int first[N],nex[M],to[M],edge[M],v[N],size[N],tot,n,k;long long dp[N][N];
char buf[L],*S,*T;
#define getchar() ((S==T&&(T=(S=buf)+fread(buf,1,L,stdin),S==T))?EOF:*S++)
inline int read(){
rg ss=;register char bb=getchar();
while(bb<||bb>)bb=getchar();
while(bb>=&&bb<=)ss=(ss<<)+(ss<<)+(bb^),bb=getchar();
return ss;
}
inline void add(rg a,rg b,rg c){
to[++tot]=b,edge[tot]=c,nex[tot]=first[a],first[a]=tot;
}
inline int max(rg a,rg b){return a>b?a:b;}
inline int min(rg a,rg b){return a<b?a:b;}
inline long long Max(long long a,long long b){return a<b?b:a;}
void dfs(int x){
int y;
size[x]=;v[x]=;
for(int i=first[x];i;i=nex[i]){
if(v[y=to[i]]) continue;
dfs(y);
rg z=edge[i];
rg qq=min(size[x],k),pp=min(size[y],k);
//倒序枚举
for(rg j=qq;j>=;--j)//这块要放到里面,原因见blog
for(rg l=pp;l>=;--l){
long long del=1ll*z*1ll*l*1ll*(k-l)+1ll*z*1ll*(size[y]-l)*1ll*(n-k-(size[y]-l));
dp[x][j+l]=Max(dp[x][j+l],dp[y][l]+dp[x][j]+del);
}
size[x]+=size[y];
}
}
signed main(){
n=read(),k=read();
k=min(k,n-k);
for(rg i=;i<n;++i){
rg x=read(),y=read(),z=read();
add(x,y,z);
add(y,x,z);
}
dfs();
printf("%lld",dp[][k]);
}
[HAOI2015][bzoj 4033]树上染色(树dp+复杂度分析)的更多相关文章
- [BZOJ 4033] 树上染色
Link: BZOJ 4033 传送门 Solution: 此题用到了计算贡献的方法, 将 多条路径的路径和 $->$ $\sum_{i=1}^{n-1} w[i]*cnt[i]$ 这样我们由 ...
- bzoj 4033 树上染色 - 树形动态规划
有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑 色,并将其他的N-K个点染成白色.将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间距离的 ...
- 洛谷 P3177 [HAOI2015]树上染色 树形DP
洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...
- bzoj 4033: [HAOI2015]树上染色 [树形DP]
4033: [HAOI2015]树上染色 我写的可是\(O(n^2)\)的树形背包! 注意j倒着枚举,而k要正着枚举,因为k可能从0开始,会使用自己更新一次 #include <iostream ...
- [HAOI2015]树上染色 树状背包 dp
#4033. [HAOI2015]树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 将其他的N-K个点染成白 ...
- [BZOJ4033][HAOI2015]树上染色(树形DP)
4033: [HAOI2015]树上染色 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2437 Solved: 1034[Submit][Stat ...
- 【BZOJ4033】[HAOI2015]树上染色 树形DP
[BZOJ4033][HAOI2015]树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染 ...
- 【HAOI2015】树上染色—树形dp
[HAOI2015]树上染色 [题目描述]有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色.将所有点染色后,你会获得 ...
- bzoj 3572世界树 虚树+dp
题目大意: 给一棵树,每次给出一些关键点,对于树上每个点,被离它最近的关键点(距离相同被标号最小的)控制 求每个关键点控制多少个点 分析: 虚树+dp dp过程如下: 第一次dp,递归求出每个点子树中 ...
随机推荐
- Linux进程自保护攻防对抗技术研究(Process Kill Technology && Process Protection Against In Linux)
0. 引言 0x1: Linux系统攻防思想 在linux下进行"进程kill"和"进程保护"的总体思路有以下几个,我们围绕这几个核心思想展开进行研究 . 直接 ...
- springboot 实时监控 spring-boot-starter-actuator 包
对java工程实时监控方式很多,本文主要讲在springboot框架中的监控. springboot框架,自带了actuator监控,在pom中引入jar包即可,如下 1.引入jar <depe ...
- 环境配置--升级Python 3.6爬坑
升级到3.6之后,发现ctrl alt t呼不出命令台,找了半天发现update manager也打不开,而且没有错误报告.....查阅了一番资料看到有人有类似的问题(https://askubunt ...
- 使用mavan构建自定义项目脚手架
首先抛出一个问题是为什么要构建自定义的脚手架,maven已经为了我么提供了很多脚手架,方便我们快速的创建一个普通java项目或者是web项目,然而在实际开发中,例如银行项目,大部分都是ssm架构,我们 ...
- jquery实现输入框实时统计字数和设置字数限制功能
<html> <header> <meta charset="utf-8"> <title>测试实时字数显示</title&g ...
- django AJAX 的应用
目录 AJAX 的使用 AJAX简介 AJAX常见应用情景 AJAX的优缺点 jQuery实现的AJAX JS实现AJAX AJAX请求如何设置csrf_token Form表单上传文件 AJAX上传 ...
- Redis 学习-安装、数据类型与 API 理解、Java 客户端
本博客是在学习<Redis从入门到高可用,分布式实践>教程时的笔记. 同时参考: https://www.cnblogs.com/jiang910/p/10020048.html 一.Re ...
- 阿里P7整理20个非常有用的Java程序片段,你知道吗?
1.字符串有整型的相互转换 String a = String.valueOf(2); //integer to numeric string int i = Integer.parseInt( ...
- Centos7安装Openresty和orange
1.说明 以下全部操作均已root用户执行 2.安装 2.1 安装依赖 yum install readline-devel pcre-devel openssl-devel gcc 2.2 下载op ...
- Flask之基础
一,flask Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求 ...