4033: [HAOI2015]树上染色

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 3461  Solved: 1473
[Submit][Status][Discuss]

Description

有一棵点数为N的树,树边有边权。给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并
将其他的N-K个点染成白色。将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间距离的和的收益。
问收益最大值是多少。

Input

第一行两个整数N,K。
接下来N-1行每行三个正整数fr,to,dis,表示该树中存在一条长度为dis的边(fr,to)。
输入保证所有点之间是联通的。
N<=2000,0<=K<=N

Output

输出一个正整数,表示收益的最大值。

Sample Input

5 2
1 2 3
1 5 1
2 3 1
2 4 2

Sample Output

17
【样例解释】
将点1,2染黑就能获得最大收益。

HINT

2017.9.12新加数据一组 By GXZlegend

Source

思路:我们知道有道题,是求两两距离之和,我们可以一遍DFS得到,即每条边的贡献=sz[v]*(N-sz[v])*Len[i];此题也一样,我们用dp[u][x]表示以u为根的子树里有x个黑点的最大收益。  不难得到DP方程。

注意这样的背包复杂度会偏大:

 for(int i=min(sz[u],K);i>=;i--){
for(int j=;j<=min(i,sz[v]);j++){
dp[u][i]=max(dp[u][i],dp[u][i-j]+dp[v][j]+1ll*j*(K-j)*Len[p[e]]+1ll*(sz[v]-j)*(N-K-sz[v]+j)*Len[p[e]]);
}
}

应该用如下:788ms

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxn=;
int Laxt[maxn],Next[maxn<<],To[maxn<<],Len[maxn<<];
int N,K,sz[maxn],cnt; ll dp[maxn][maxn];
void add(int u,int v,int w){
Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
}
void dfs(int u,int f){
sz[u]=; dp[u][]=dp[u][]=;
for(int e=Laxt[u];e;e=Next[e]){
int v=To[e]; if(v==f) return ;
dfs(v,u);
for(int i=min(sz[u],K);i>=;i--){
for(int j=min(sz[v],K-i);j>=;j--){
dp[u][i+j]=max(dp[u][i+j],dp[u][i]+dp[v][j]+1ll*j*(K-j)*Len[e]+1ll*(sz[v]-j)*(N-K-sz[v]+j)*Len[e]);
}
}
sz[u]+=sz[v];
}
}
int main()
{
int u,v,w;
scanf("%d%d",&N,&K);
rep(i,,N-){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w); add(v,u,w);
}
dfs(,);
printf("%lld\n",dp[][K]);
return ;
}

也可以先排序:692ms

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxn=;
int Laxt[maxn],Next[maxn<<],To[maxn<<],Len[maxn<<];
int N,K,sz[maxn],cnt,son[maxn]; ll dp[maxn][maxn];
bool cmp(int w,int v) {return sz[To[w]]<sz[To[v]]; }
void add(int u,int v,int w){
Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
}
void dfs1(int u,int f){
sz[u]=; for(int e=Laxt[u];e;e=Next[e]){
if(To[e]!=f) dfs1(To[e],u),sz[u]+=sz[To[e]];
}
}
void dfs2(int u,int f){
int tot=,p[maxn]; dp[u][]=dp[u][]=; son[u]=;
for(int e=Laxt[u];e;e=Next[e]) if(To[e]!=f) p[++tot]=e;
sort(p+,p+tot+,cmp);
for(int e=;e<=tot;e++){
int v=To[p[e]]; if(v==f) return ;
dfs2(v,u);
for(int i=min(son[u],K);i>=;i--){
for(int j=min(son[v],K-i);j>=;j--){
dp[u][i+j]=max(dp[u][i+j],dp[u][i]+dp[v][j]+1ll*j*(K-j)*Len[p[e]]+1ll*(sz[v]-j)*(N-K-sz[v]+j)*Len[p[e]]);
}
}
son[u]+=son[v];
}
}
int main()
{
int u,v,w;
scanf("%d%d",&N,&K);
rep(i,,N-){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w); add(v,u,w);
}
dfs1(,); dfs2(,);
printf("%lld\n",dp[][K]);
return ;
}

BZOJ4033: [HAOI2015]树上染色(树形DP)的更多相关文章

  1. [BZOJ4033][HAOI2015]树上染色(树形DP)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2437  Solved: 1034[Submit][Stat ...

  2. bzoj4033 [HAOI2015]树上染色——树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4033 树形DP,状态中加入 x 与父亲之间的边的贡献: 边权竟然是long long... ...

  3. 洛谷 P3177 [HAOI2015]树上染色 树形DP

    洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...

  4. 【BZOJ4033】[HAOI2015]树上染色 树形DP

    [BZOJ4033][HAOI2015]树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染 ...

  5. bzoj 4033: [HAOI2015]树上染色 [树形DP]

    4033: [HAOI2015]树上染色 我写的可是\(O(n^2)\)的树形背包! 注意j倒着枚举,而k要正着枚举,因为k可能从0开始,会使用自己更新一次 #include <iostream ...

  6. BZOJ 4033 [HAOI2015]树上染色 ——树形DP

    可以去UOJ看出题人的题解. 这样的合并,每一个点对只在lca处被考虑到,复杂度$O(n^2)$ #include <map> #include <ctime> #includ ...

  7. BZOJ4033 HAOI2015 树上染色 【树上背包】

    BZOJ4033 HAOI2015 树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白 ...

  8. [bzoj4033][HAOI2015]树上染色_树形dp

    树上染色 bzoj-4033 HAOI-2015 题目大意:给定一棵n个点的树,让你在其中选出k个作为黑点,其余的是白点,收益为任意两个同色点之间距离的和.求最大收益. 注释:$1\le n\le 2 ...

  9. 【BZOJ4033】【HAOI2015】树上染色 树形DP

    题目描述 给你一棵\(n\)个点的树,你要把其中\(k\)个点染成黑色,剩下\(n-k\)个点染成白色.要求黑点两两之间的距离加上白点两两之间距离的和最大.问你最大的和是多少. \(n\leq 200 ...

随机推荐

  1. wordpress防止网站被镜像四个方法

    第一种:拆分域名链接与镜像站比对,然后用img标签src空值触发onerror来执行js比对,比对失败则跳转回源站.代码如下:(复制粘贴到主题的functions.php最后一个?>之前,代码出 ...

  2. hdu5072 容斥+枚举

    这题说的是给了 n 个数字 每个数值大于1 小于100000,n小于100000 ,找出满足下面要求的三人组有多少种 比如abc ( (ab)==(bc)==(ac) ==1 )||( (ab)!=1 ...

  3. animation CSS3动画总结

    最近一个小游戏项目用到了CSS3的动画属性,例如transition.transform.animation.经过三个星期,终于做完了,利用周末好好梳理总结一下. keyframes这个属性用来定义一 ...

  4. CentOS下安装JDK,Tomcat,Redis,Mysql,及项目发布

    上传文件到服务器,安装lrzsz , 可以将本地的文件上传到linux系统上. 如果是CentOS则可以用yum install lrzsz 命令安装,更方便. 或:yum -y install lr ...

  5. bzoj1625 / P2871 [USACO07DEC]手链Charm Bracelet

    P2871 [USACO07DEC]手链Charm Bracelet 裸01背包. 看到自己1年半前写的30分code.......菜的真实(捂脸) #include<iostream> ...

  6. 2018-2019-1 20189215《Linux内核原理与分析》第三周作业

    <庖丁解牛>第二章书本知识总结 函数调用框架 call指令有两个作用: (1) 将CS:EIP中下一条指令的地址A保存在栈顶: (2)设置CS:EIP指向被调用程序的第一行. ret指令在 ...

  7. CentOS7.2 安装Chrome

    /etc/yum.repos.d/目录下新建文件google-chrome.repo,向其中添加如下内容: [google-chrome] name=google-chrome baseurl=htt ...

  8. 试着用React写项目-利用styled-components解决样式问题

    转载请注明出处:王亟亟的大牛之路 啰嗦之前先安利,会渐渐丰富前端的知识点 https://github.com/ddwhan0123/Useful-Open-Source-Android 昨天用web ...

  9. [转][修]sprintf()函数:将格式化的数据写入字符串

    头文件:#include <stdio.h>功能:用于将格式化的数据写入字符串 原型:int sprintf(char *str, char * format [, argument, . ...

  10. spark内存管理分析

    前言 下面的分析基于对spark2.1.0版本的分析,对于1.x的版本可以有区别. 内存配置 key 默认 解释 spark.memory.fraction 0.6 spark可以直接使用的内存大小系 ...