Luogu P3177 [HAOI2015]树上染色
一道有机结合了计数和贪心这一DP两大考点的神仙题,不得不说做法是很玄妙。
首先我们很容易想到DP,设\(f_{i,j}\)表示在以\(i\)为根节点的子树中选\(j\)个黑色节点的最大收益值。
然后我们考虑那种暴力转移就是那种看上去是\(O(n^3)\)实际经严格证明后时\(O(n^2)\)的DP
然后推推推推推推,一个小时过去还是一个屁
这个时候我们不禁质疑,这个鬼状态不会是错的吧。
没错,它就是错的,因为这样对于你子树上面的黑点节点之间的收益你都一无所知
然后我们联想到另外一道树上计数的题目:51Nod 1677 treecnt&&sol,然后我们又是单独考虑每一条边的贡献。
再仔细推一波可以发现一条边对于黑白点的贡献之和两边黑白点的个数有关,和具体的结构鸟关系都没有。
于是我们换一波方程,设\(f_{i,j}\)表示在以\(i\)为根节点的子树中选\(j\)个黑色节点对总答案的贡献
然后我们枚举子树中黑色点的数量然后一个类似于背包的转移即可。
具体看CODE
#include<cstdio>
#include<cctype>
#include<cstring>
using namespace std;
const int N=2005;
struct edge
{
int to,next,v;
}e[N<<1];
int head[N],size[N],n,k,cnt,x,y,z,rt=1;
long long f[N][N];
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch; while (!isdigit(ch=tc()));
while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline void double_add(int x,int y,int z)
{
e[++cnt].to=y; e[cnt].next=head[x]; e[cnt].v=z; head[x]=cnt;
e[++cnt].to=x; e[cnt].next=head[y]; e[cnt].v=z; head[y]=cnt;
}
inline void maxer(long long &x,long long y)
{
if (y>x) x=y;
}
inline int min(int a,int b)
{
return a<b?a:b;
}
inline void DFS(int now,int fa)
{
register int i,j,s,x; size[now]=1;
f[now][0]=f[now][1]=0;
for (i=head[now];~i;i=e[i].next)
if (e[i].to!=fa) DFS(e[i].to,now),size[now]+=size[e[i].to];
for (i=head[now];~i;i=e[i].next)
if (e[i].to!=fa) for (j=min(k,size[now]);j>=0;--j)
{
for (s=0,x=min(j,size[e[i].to]);s<=x;++s)
maxer(f[now][j],f[e[i].to][s]+f[now][j-s]+1LL*e[i].v*(1LL*s*(k-s)+1LL*(size[e[i].to]-s)*(n-k-size[e[i].to]+s)));
}
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i; read(n); read(k);
if (2*k>n) k=n-k;
memset(head,-1,sizeof(head)); memset(f,167,sizeof(f));
for (i=1;i<n;++i)
read(x),read(y),read(z),double_add(x,y,z);
DFS(rt,-1); return printf("%lld",f[rt][k]),0;
}
注意上面的一个小trick:
if (2*k>n) k=n-k;
这样对无关的常数浪费就会大大降低直接帮助我卡过了BZOJ的老爷机,不加T死
Luogu P3177 [HAOI2015]树上染色的更多相关文章
- 洛谷 P3177 [HAOI2015]树上染色 树形DP
洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...
- P3177 [HAOI2015]树上染色
题目描述 有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 . 将所有点染色后,你会获得黑点两两之 ...
- 洛谷 P3177 [HAOI2015]树上染色
题目链接 题目描述 有一棵点数为 \(N\) 的树,树边有边权.给你一个在 \(0~ N\) 之内的正整数 \(K\) ,你要在这棵树中选择 \(K\)个点,将其染成黑色,并将其他 的\(N-K\)个 ...
- 【洛谷】P3177 [HAOI2015]树上染色
懒得复制题面了直接传送门吧 分析 直接求点与点之间的距离感觉不是很好求,所以我们考虑换一个求法. 瞄了一眼题解 距离跟路径上边的长度有关,所以我们直接来看每一条边的贡献吧(这谁想得到啊) 对于每一条边 ...
- 洛谷P3177 [HAOI2015]树上染色(树形dp)
题目描述 有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 . 将所有点染色后,你会获得黑点两两之 ...
- 洛谷P3177 [HAOI2015]树上染色(树上背包)
题意 题目链接 Sol 比较套路吧,设\(f[i][j]\)表示以\(i\)为根的子树中选了\(j\)个黑点对答案的贡献 然后考虑每条边的贡献,边的两边的答案都是可以算出来的 转移的时候背包一下. # ...
- BZOJ 4033: [HAOI2015]树上染色题解
BZOJ 4033: [HAOI2015]树上染色题解(树形dp) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327400 原题地址: BZOJ 403 ...
- bzoj 4033: [HAOI2015]树上染色 [树形DP]
4033: [HAOI2015]树上染色 我写的可是\(O(n^2)\)的树形背包! 注意j倒着枚举,而k要正着枚举,因为k可能从0开始,会使用自己更新一次 #include <iostream ...
- BZOJ4033: [HAOI2015]树上染色(树形DP)
4033: [HAOI2015]树上染色 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 3461 Solved: 1473[Submit][Stat ...
随机推荐
- 《Inside C#》笔记(八) 接口
接口可以认为是属于不同继承树的代码之间的行为约定.C#的接口相当于是一种特殊的抽象类,这种抽象类的内部只有虚方法. 一 接口的使用 a) 接口内部可以包含方法.属性.索引器和事件,这些成员都不在接口中 ...
- js判断当前浏览器语言类型
console.log(window.navigator.language.slice(0, 2)); 得到的是zh
- 前端使用 validate , 根据条件进行动态的验证添加
需求如下: 审核操作的时候,选择“通过” 就不需要验证审核意见,但是选择的是“不通过”,那么需要进行审核意见验证 <script> $(function () { InitValidate ...
- SSO阅读有感
SSO比较详细且理解.赞 链接:https://www.cnblogs.com/ywlaker/p/6113927.html
- 转:tcpdump抓包分析(强烈推荐)
转自:https://mp.weixin.qq.com/s?__biz=MzAxODI5ODMwOA==&mid=2666539134&idx=1&sn=5166f0aac71 ...
- 阿里八八β阶段Scrum(2/5)
今日进度 黄梅玲:尝试修复日程界面的不可点击问题 李嘉群:修改数据库,增加写入识别功能临时文本存入的项 张岳:信息抽取算法的编写 叶文滔:尝试侧边栏的信息调用,但因为侧边栏不是单独的活动,调用碰到了困 ...
- 浅析JAVA中堆内存与栈内存的区别
Java把内存划分成两种:一种是栈内存,一种是堆内存. 一.栈内存 存放基本类型的变量,对象的引用和方法调用,遵循先入后出的原则. 栈内存在函数中定义的“一些基本类型的变量和对象的引用变量”都 ...
- 【Android自动化】测试android手机唤醒性能测试
# -*- coding:utf-8 -*- import time import os import common.common from common.getconfigs import GetC ...
- 详解JavaScript中void语句的使用
void是在JavaScript中的一个重要的关键字可被用作其单操作数之前出现一元运算符,其可以是任何类型. 此运算符指定不需要返回值,进行计算的表达式.它的语法可能是下列之一: <script ...
- Properties集合_list方法与store方法
Properties集合和流对象结合的功能 list()方法: import java.util.Properties; public class PropertiesDemo { public st ...