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

Solution

比较经典的树形背包问题。

如果只对点进行分析,情况会变得十分麻烦,不放考虑每条变的贡献,每条边会产生两边黑点数的乘积加上两边白点数的乘积。

这样的话我们直接跑背包就可以了,标准的树形背包是n^3的,但是这道题每颗字数背包体积有上限,总复杂度可以做到n^2.

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 2009
using namespace std;
long long dp[N][N];
int size[N],m,n,a,b,c,tot,head[N];
struct dsd
{int n,to,l;
}an[N<<1];
inline void add(int u,int v,int l)
{an[++tot].n=head[u];an[tot].to=v;head[u]=tot;an[tot].l=l;
}
void dfs(int u,int fa)
{size[u]=1;for(int i=head[u];i;i=an[i].n)if(an[i].to!=fa){int v=an[i].to;dfs(v,u);size[u]+=size[v];for(int j=min(m,size[u]);j>=0;--j)//
      for(int k=0;k<=min(j,size[v]);++k)if(dp[v][k]!=-0x3f3f3f3f){long long num=(long long)(k*(m-k)+(n-size[v]-(m-k))*(size[v]-k))*an[i].l;dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]+num);}}
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<n;++i){scanf("%d%d%d",&a,&b,&c);add(a,b,c);add(b,a,c);}memset(dp,-0x3f,sizeof(dp));for(int i=1;i<=n;++i)dp[i][0]=dp[i][1]=0;//
    dfs(1,0);cout<<dp[1][m];return 0;
} 

这种写法太慢了,并没有做到严格n^2,bzoj会TLE,下面这种写法是稳过的。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 2009
using namespace std;
typedef long long ll;
ll dp[N][N],size[N],m,n,a,b,c,tot,head[N],g[N];
struct dsd
{ll n,to,l;
}an[N<<1];
inline void add(ll u,ll v,ll l)
{an[++tot].n=head[u];an[tot].to=v;head[u]=tot;an[tot].l=l;
}
ll mi(ll x,ll y){return x<y?x:y;}
ll ma(ll x,ll y){return x<y?y:x;}
void dfs(ll u,ll fa){size[u]=1;for(ll i=head[u];i;i=an[i].n)if(an[i].to!=fa){ll v=an[i].to;dfs(v,u);ll x=mi(m,size[u]),y=mi(m,size[v]);for(int j=0;j<=m;++j)g[j]=0;for(ll j=x;j>=0;--j)for(int k=0;k<=y;++k)if(j+k<=m){ll gyx=((ll)k*(m-k)+(n-size[v]-(m-k))*(size[v]-k))*an[i].l;g[j+k]=ma(g[j+k],dp[u][j]+dp[v][k]+gyx);}for(int j=0;j<=m;++j)dp[u][j]=g[j];size[u]+=size[v];}
}
inline int rd(){int x=0;char c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}return x;
}
int main()
{n=rd();m=rd();for(int i=1;i<n;++i){a=rd();b=rd();c=rd();add(a,b,c);add(b,a,c);}memset(dp,-0x3f,sizeof(dp));for(int i=1;i<=n;++i)dp[i][0]=dp[i][1]=0;dfs(1,0);printf("%lld",dp[1][m]);return 0;
} 

转载于:https://www.cnblogs.com/ZH-comld/p/9737789.html

[HAOI2015]树上染色(树形背包)相关推荐

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

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

  2. bzoj4033: [HAOI2015]树上染色(树形dp)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 3269  Solved: 1413 [Submit][St ...

  3. Luogu P3177 [HAOI2015] 树上染色(树上背包)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Luogu P3177 [HAOI2015] 树上染色 有一棵点数为 NNN 的树,树边有边权.给你一 ...

  4. bzoj 4033: [HAOI2015]树上染色(树形DP)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 1786  Solved: 754 [Submit][Sta ...

  5. [BZOJ4033][HAOI2015]树上染色

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2108  Solved: 901 [Submit][Sta ...

  6. [HAOI2015]树上染色(树形dp,树形背包)

    链接:https://ac.nowcoder.com/acm/problem/19996 来源:牛客网 题目描述 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个 ...

  7. 洛谷 P3177 [HAOI2015]树上染色

    题目链接 题目描述 有一棵点数为 \(N\) 的树,树边有边权.给你一个在 \(0~ N\) 之内的正整数 \(K\) ,你要在这棵树中选择 \(K\)个点,将其染成黑色,并将其他 的\(N-K\)个 ...

  8. BZOJ 4033: [HAOI2015]树上染色

    题解:看着题目感到恐惧,什么一个点选黑选白要是1e5我肯定会往淀粉质想了,就很害怕,我又不会..然后一看数据范围2000,于是突然开心,想写题.N-N^2应该美滋滋?dp[x][k]表示x的子树中选择 ...

  9. bzoj4033 [HAOI2015]树上染色

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4033 重要的思路:与其考虑每一个点对的贡献,不如考虑每条边的贡献(==被经过了几次)! 树形 ...

最新文章

  1. 京东超大规模联邦学习探索实践
  2. java se翻译_(翻译)Java SE 8 Lambda 标准库概览(下)
  3. oracle 服务管理,管理 Oracle 内容服务类别
  4. java pc计数器_java虚拟机-程序计数器PC Register
  5. 使用Java中的equals()和compareTo()方法比较字符串
  6. 深入了解Zookeeper核心原理
  7. react-native ios打包和Android打包
  8. linux 查询 lib信息,linux系统信息常用查询命令
  9. windows下db2的一些使用心得(不含安装)
  10. mybatis 业务逻辑
  11. 《编写有效用例》阅读笔记05
  12. 使用apache benchmark(ab) 测试报错: apr_socket_recv: Connection timed out (110)
  13. 让基础设施代码化更加容易,pulumi 都做了些什么?
  14. 微软去年安全业务收入150亿美元、新勒索软件以威联通设备为目标|1月27日全球网络安全热点
  15. CI框架实现某字段自加数值
  16. 本周上榜的这9本原创技术书很赞,《数学之美》作者吴军博士新书霸榜
  17. 微信小程序开发工具整理代码快捷键
  18. python识别二维码条形码?用pyzbar一招搞掂(含代码)!
  19. 云原生编程语言ballerina:hello-world
  20. CTF-RSA分解模数N

热门文章

  1. 使用bat执行java项目
  2. VB循环For的一点启示
  3. Linux环境下利用句柄恢复Oracle误删除的数据文件
  4. SQL注入之Mysql报错注入
  5. mysql 用户权限设置【转】
  6. Hadoop: The Definitive Guide (3rd Edition)
  7. HDFS Federation机制
  8. 关于FPGA核心bug解决
  9. (90)AXI突发式读写时序和过程
  10. (70)信号发生器DDS正弦波设计(二)(第14天)