一道很好的树形 dp !!!!!

树上染色

错误思路

定义 \(dp[u][i]\) 表示以 \(u\) 为根的子树中,把 \(i\) 个点染成黑色的最大收益。

但这样写,就在转移的时候必须枚举每一个点,复杂度过大,而且还不好写,是十分错误的写法。

正确思路

一般看到有关树上“路径”的题,就要把路径拆成一个个独立的单边,对每个单边独立计算贡献。

我们尝试对某一条边 \((u,v)\) 进行考虑( \(u\) 为父亲,\(v\) 为儿子):

设儿子下面有 \(j\) 个黑点,整棵树有 \(k\) 个黑点,树上总共 \(n\) 个点 ,以 \(x\) 为根的子树的点数为 \(sz[x]\) 。

那么经过这条边的路径总数为:儿子下面和父亲上面的黑点的路径数 \((j*(k-j))\) 以及儿子下面和父亲上面的白点的路径数 \(((sz[v]-j)*(n-sz[v]-(k-j)))\) 的和。

然后乘上这条边的长度 \(w_i\) 。

\[(j*(k-j)+(sz[v]-j)*(n-sz[v]-(k-j)))*w_i
\]

就是这条边的贡献。

于是 dp 状态就出来了:

定义 \(dp[u][i]\) 表示 以 \(u\) 为根的子树中,选 \(i\) 个点作为黑点,对答案整体的最大贡献

对于转移,我们只需要考虑 \(u\) 与 \(v\) 中的那条边,然后像树形背包一样转移就好了:

\[dp[u][i]=max(dp[u][i],dp[u][i-j]+dp[v][j]+(j*(k-j)+(sz[v]-j)*(n-sz[v]-(k-j)))*w_i)
\]

细节处理

上界的处理(for(int i=min(k,sz[u]);i>=0;i--)for(int j=0;j<=min(i,sz[v]);j++))不必多说,这题的坑点在于下界:

考虑一条链的数据,对于一个点 \(u\) ,其子树的黑色点个数一定是 以 \(u\) 为根的树的黑色点个数 或者 比以 \(u\) 为根的树的黑色点个数少 \(1\) 。

所以如果我们不控制循环的下界,那么在链的 hack 下复杂度将直逼 \(O(n^3)\) 。

这是因为除去该子树,自己父节点下的其他子树的总结点数比 \(i-j\) 小,造成无效转移。

所以解一个不等式:

\[i-j \le sz[u]-sz[v]
\]

解得

\[j \ge i-sz[u]+sz[v]
\]

这就是 \(j\) 的下界。

时间复杂度 \(O(n^2)\) 。

树形背包检验自己复杂度正确与否,只需要构造一条链的数据,看看会不会被卡成立方的就好了。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,k,sz[2005];
struct edge{
int to;
ll w;
};
vector<edge>s[2005];
ll dp[2005][2005];
void dfs(int u,int fa)
{
sz[u]=1;
for(auto tmp:s[u])
{
int v=tmp.to;
ll w=tmp.w;
if(v==fa)continue;
dfs(v,u);
sz[u]+=sz[v];
for(int i=min(k,sz[u]);i>=0;i--)
{
for(int j=max(0,i-sz[u]+sz[v]);j<=min(i,sz[v]);j++)
{
dp[u][i]=max(dp[u][i],dp[v][j]+dp[u][i-j]+(1ll*j*(k-j)+1ll*(sz[v]-j)*(n-k-(sz[v]-j)))*w);
}
}
}
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n-1;i++)
{
int u,v;
ll w;
cin>>u>>v>>w;
s[u].push_back({v,w});
s[v].push_back({u,w});
}
dfs(1,0);
cout<<dp[1][k];
return 0;
}

Luogu P3177 树上染色 [ 蓝 ] [ 树形 dp ] [ 贡献思维 ]的更多相关文章

  1. 2021.07.17 P3177 树上染色(树形DP)

    2021.07.17 P3177 树上染色(树形DP) [P3177 HAOI2015]树上染色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 重点: 1.dp思想是需要什么,维护 ...

  2. 【Luogu】P3177树上染色(树形DP)

    题目链接 题没想出来很烦+一堆细节要注意很烦. 当然更可能是我智商被osu吃了. 考虑一条边会有什么贡献?它一边的黑点数*另一边的黑点数*边权. +它一边的白点数*另一边的白点数*边权. 这样一来就成 ...

  3. BZOJ_4033_[HAOI2015]树上染色_树形DP

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

  4. 洛谷P3177 [HAOI2015]树上染色(树形dp)

    题目描述 有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 . 将所有点染色后,你会获得黑点两两之 ...

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

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

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

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

  7. [HAOI2015]树上染色(树形dp)

    [HAOI2015]树上染色 题目描述 有一棵点数为 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个点染成白色.要求你求出黑点两两之间的距离加上白点两两之间距离的和的最大值. 树形\(DP\) 这道 ...

  10. BZOJ4033 [HAOI2015]树上染色 【树形dp】

    题目 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 将其他的N-K个点染成白色.将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间 ...

随机推荐

  1. brew之加速

    有没有出现这种场景:使用brew install 安装程序,一直卡在brew updating,这可能是使用着默认的github镜像源导致,那么我们就需要将其切换到国内 1.镜像切换(推荐中科大) 1 ...

  2. nginx之访问控制

    Nginx的源码提供了ngx_http_auth_basic_module这个模块,它可以来解决web访问认证的问题.这个模块是默认就编译进nginx的,可以直接拿来使用. ngx_http_auth ...

  3. wps文字表格邮件附件部分图片无法预览的问题(1)

    使用邮箱客户端发送带word附件的邮件时,客户说部分图片无法查看.我方人员测试下,得到如下几点: 1.出问题的.docx文件下载后可以正常打开查看,但通过给自己邮箱转发邮件(包含附件),foxmail ...

  4. 1分钟学会如何提升PCIe通信速率,基于RK3568J + FPGA国产平台!

    测试数据汇总 表 1 PCIe总线介绍 PCIe,即PCI-Express(peripheral component interconnect express)是一种高速串行计算机扩展总线标准.主要用 ...

  5. Linux禁止某个sudo用户修改root密码

    (1) 假设被禁止的sudo用户名为 user (2) 禁止user用户使用passwd命令更改密码(非最终配置) vim /etc/sudoers 加入 user ALL=(root)!/usr/b ...

  6. uni-app Vue3项目引入Tailwind CSS

    前情 Tailwind CSS 是一个原子类 CSS 框架,它将基础的 CSS 全部拆分为原子级别,同时还补全各种浏览器模式前缀,兼容性也不错.它的工作原理是扫描所有 HTML 文件.JavaScri ...

  7. SpringBoot配置文件敏感信息加密,springboot配置文件数据库密码加密jasypt

    使用过SpringBoot配置文件的朋友都知道,资源文件中的内容通常情况下是明文显示,安全性就比较低一些.打开application.properties或application.yml,比如mysq ...

  8. Qt/C++地图导航app/支持qml/手机运行/输入起点终点规划路径/模拟轨迹移动

    一.前言说明 搞Qt地图开发这块,随着研究的深入,用户的需求变化,最近又需要在手机上运行,由于本地图组件依赖浏览器控件,而手机安卓上的Qt并没有带qwebengine控件,怎么办呢,不断的努力验证下, ...

  9. docker导入和导出

    save和export 镜像导入和导出有2种方式,分别为 save和load.export和import save导出的是镜像:export导出的为容器 save导出会保存镜像所有的提交记录:expo ...

  10. CSS JS 自适应菜单

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...