Luogu P3177 树上染色 [ 蓝 ] [ 树形 dp ] [ 贡献思维 ]
一道很好的树形 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\) 。
\]
就是这条边的贡献。
于是 dp 状态就出来了:
定义 \(dp[u][i]\) 表示 以 \(u\) 为根的子树中,选 \(i\) 个点作为黑点,对答案整体的最大贡献。
对于转移,我们只需要考虑 \(u\) 与 \(v\) 中的那条边,然后像树形背包一样转移就好了:
\]
细节处理
上界的处理(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\) 小,造成无效转移。
所以解一个不等式:
\]
解得
\]
这就是 \(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 ] [ 贡献思维 ]的更多相关文章
- 2021.07.17 P3177 树上染色(树形DP)
2021.07.17 P3177 树上染色(树形DP) [P3177 HAOI2015]树上染色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 重点: 1.dp思想是需要什么,维护 ...
- 【Luogu】P3177树上染色(树形DP)
题目链接 题没想出来很烦+一堆细节要注意很烦. 当然更可能是我智商被osu吃了. 考虑一条边会有什么贡献?它一边的黑点数*另一边的黑点数*边权. +它一边的白点数*另一边的白点数*边权. 这样一来就成 ...
- BZOJ_4033_[HAOI2015]树上染色_树形DP
BZOJ_4033_[HAOI2015]树上染色_树形DP Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 将其他的 ...
- 洛谷P3177 [HAOI2015]树上染色(树形dp)
题目描述 有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 . 将所有点染色后,你会获得黑点两两之 ...
- BZOJ4033: [HAOI2015]树上染色(树形DP)
4033: [HAOI2015]树上染色 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 3461 Solved: 1473[Submit][Stat ...
- BZOJ 4033[HAOI2015] 树上染色(树形DP)
4033: [HAOI2015]树上染色 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 3188 Solved: 1366[Submit][Stat ...
- [HAOI2015]树上染色(树形dp)
[HAOI2015]树上染色 题目描述 有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 . 将所 ...
- [bzoj4033][HAOI2015]树上染色_树形dp
树上染色 bzoj-4033 HAOI-2015 题目大意:给定一棵n个点的树,让你在其中选出k个作为黑点,其余的是白点,收益为任意两个同色点之间距离的和.求最大收益. 注释:$1\le n\le 2 ...
- 【BZOJ4033】[HAOI2015] 树上染色(树形DP)
点此看题面 大致题意: 给你一棵点数为N的带权树,要你在这棵树中选择K个点染成黑色,并将其他的N-K个点染成白色.要求你求出黑点两两之间的距离加上白点两两之间距离的和的最大值. 树形\(DP\) 这道 ...
- BZOJ4033 [HAOI2015]树上染色 【树形dp】
题目 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 将其他的N-K个点染成白色.将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间 ...
随机推荐
- Windows下的终端工具-Terminal
文档:https://docs.microsoft.com/zh-cn/windows/terminal/ Windows 终端是一个面向命令行工具和 shell(如命令提示符.PowerShell ...
- C#使用CsRedis操作Redis
C#使用CsRedis操作Redis 转:脚本之家(https://www.jb51.net/article/201034.htm) 现在流行的redis连接客户端有StackExchange.Red ...
- 【C#】【报错解决】分析器错误消息: 未能找到 CodeDom 提供程序类型“Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider
1.工具->NuGet包管理器->程序包管理控制台 2.在程序包管理控制台中输入 PM> Install-Package Microsoft.CodeDom.Providers.Do ...
- 【Linux】【UOS】为挂载的磁盘创建快捷方式(软链接)
打开项目或者保存文件的时候,如果需求路径不是系统盘路径,那么找起来还真是麻烦.以下时候通过创建快捷方式(软链接)的方式,将打开磁盘的快捷方式放在用户目录下,就方便寻找打开了. 1.查询挂载点 sudo ...
- Mysql数据库连接失败SSLException: Unsupported record version Unknown-0.0
问题描述:mysql版本:5.7.27jdk版本:1.8.0_201 tomcat日志中报错,显示连接数据库失败,报错信息如下: The last packet successfully receiv ...
- python 检测免费代理ip是否有效
python 检测免费代理ip是否有效,免费ip获取地址https://www.zdaye.com/free/ import requests IPAgents = [ "218.89.51 ...
- Intellij IDEA开发环境中Springboot项目无Run ****main()的菜单
问题描述: Intellij IDEA开发环境中Springboot项目无Run ****main()的菜单. 解决办法有以下几种: 方法1:Idea无右键run选项, 无法通过main方法启动sp ...
- [转]C#的二进制文件操作及关于Encoding类与汉字编码转换的问题
1.数值应保存在二进制文件 首先列举文本.二进制文件的操作(读写)方法: 方式1: //文本文件操作:创建/读取/拷贝/删除 using System; using System.IO; class ...
- Web网页端IM产品RainbowChat-Web的v7.2版已发布
一.关于RainbowChat-Web RainbowChat-Web是一套Web网页端IM系统,是RainbowChat的姊妹系统(RainbowChat是一套基于开源IM聊天框架 MobileIM ...
- 基于NVIDIA NGC容器安装使用PaddlePaddle
基于NVIDIA NGC容器安装使用PaddlePaddle PaddlePaddle PaddlePaddle作为国内首个自主研发的深度学习平台,自2016年正式向专业社区开源,是一个技术先进.功能 ...