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

题目描述

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

输入格式

第一行包含两个整数 \(n,k\)。

第二到 \(n\) 行每行三个正整数 \(fr,to,dis\)表示该树中存在一条长度为 \(dis\) 的边 \((fr, to)\)。输入保证所有点之间是联通的。

输出格式

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

输入输出样例

输入 #1

3 1

1 2 1

1 3 2

输出 #1

3

说明/提示

对于 \(100\%\) 的数据,\(0≤n,k≤2000\)

分析

很好想的一个树形\(dp\)是设\(f[i][j]\)为当前以\(i\)节点为根的子树中选了\(j\)个黑点所贡献的最大价值

注意状态的定义,是贡献多少而不是总和为多少,因此我们当前只需要考虑新加入的这条边的贡献

即边权乘以两边的白点数量之积+边权乘以两边的黑点数量之积

剩下的做一个树上的背包即可

下面我们来考虑复杂度的问题

递归中有两层循环,看起来似乎是\(n^3\)

但是它的复杂度实际上是\(n^2\)的

因为我们递归到某一个点时,枚举的是以这个点为\(LCA\)的所有点对

而每一个点对只有一个\(LCA\)

一个节点数为\(n\)的树最多有\(n^2\)个这样的点对

因此复杂度为\(n^2\)

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
inline int read(){
int x=0,fh=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
const int maxn=2005;
int n,k,tot=1,head[maxn];
struct asd{
int from,to,next,val;
}b[maxn<<1];
void ad(int aa,int bb,int cc){
b[tot].from=aa;
b[tot].to=bb;
b[tot].next=head[aa];
b[tot].val=cc;
head[aa]=tot++;
}
int siz[maxn];
long long f[maxn][maxn];
void dfs(int now,int fa){
siz[now]=1;
for(int i=head[now];i!=-1;i=b[i].next){
int u=b[i].to;
if(u==fa) continue;
dfs(u,now);
for(int j=siz[now];j>=0;j--){
for(int kk=siz[u];kk>=0;kk--){
long long nans=1LL*f[now][j]+f[u][kk]+1LL*b[i].val*kk*(k-kk)+1LL*b[i].val*(siz[u]-kk)*((n-k)-(siz[u]-kk));
f[now][j+kk]=std::max(f[now][j+kk],nans);
}
}
siz[now]+=siz[u];
}
}
int main(){
memset(head,-1,sizeof(head));
n=read(),k=read();
for(int i=1;i<n;i++){
int aa,bb,cc;
aa=read(),bb=read(),cc=read();
ad(aa,bb,cc),ad(bb,aa,cc);
}
dfs(1,0);
printf("%lld\n",f[1][k]);
return 0;
}

洛谷 P3177 [HAOI2015]树上染色 树形DP的更多相关文章

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

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

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

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

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

    题意 题目链接 Sol 比较套路吧,设\(f[i][j]\)表示以\(i\)为根的子树中选了\(j\)个黑点对答案的贡献 然后考虑每条边的贡献,边的两边的答案都是可以算出来的 转移的时候背包一下. # ...

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

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

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

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

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

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

  7. BZOJ4033或洛谷3177 [HAOI2015]树上染色

    BZOJ原题链接 洛谷原题链接 很明显的树形\(DP\). 因为记录每个点的贡献很难,所以我们可以统计每条边的贡献. 对于每一条边,设边一侧的黑点有\(B_x\)个,白点有\(W_x\),另一侧黑点有 ...

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

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

  9. 洛谷 3177 [HAOI2015] 树上染色

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

随机推荐

  1. 数据分析First week(7.15~7.21)

    描述统计学 当我们面对大量信息的时候,经常会出现数据越多,事实越模糊的情况,因此我们需要对数据进行简化,描述统计学就是用几个关键的数字来描述数据集的整体情况. 1.集中趋势 1.1 众数 众数是样本观 ...

  2. sqlzoo刷题 SELECT from Nobel Tutorial

    SELECT from Nobel Tutorial 1.Change the query shown so that it displays Nobel prizes for 1950. SELEC ...

  3. Ubuntu定时执行任务(定时爬取数据)

    cron是一个Linux下的后台进程,用来定期的执行一些任务.因为我用的是Ubuntu,所以这篇文章中的所有命令也只能保证在Ubuntu下有效. 1:编辑crontab文件,用来存放你要执行的命令 s ...

  4. LinuX操作系统基础------> 用户管理,grep搜索

    用户管理 用户组管理 字符管理和grep搜索 1.用户管理: LinuX是一个多用户,多任务的操作系统,可以让多个用户使用,这个账号可以帮助对用户进行追踪,必须在初始化的时候设置好自己的密码 1-1配 ...

  5. Python 面向对象之高级编程

    7.面向对象高级编程 7.1使用__slots__ python动态语言,new 对象后绑定属性和方法 Tip:给一个实例绑定的方法,对其他对象无效.可以通过对class绑定后,所有对象可以调用该方法 ...

  6. Springboot开启事务的支持

    主要分为两步 步骤一.在main方法加上@EnableTransactionManagement注解: @SpringBootApplication @EnableTransactionManagem ...

  7. 《Head First 设计模式》:命令模式

    正文 一.定义 命令模式将"请求"封装成对象(命令对象),以便使用不同的"请求"来参数化其他对象. 要点: 命令模式可将"动作的请求者"从& ...

  8. C#LeetCode刷题之#532-数组中的K-diff数对(K-diff Pairs in an Array)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3716 访问. 给定一个整数数组和一个整数 k, 你需要在数组里找 ...

  9. Javascript 函数成员导出

    同级目录下 文件1 // exportByModule.js const hello_1 = () => { console.info('hello_1') } const hello_2 = ...

  10. JavaScript基础-03

    1. 条件判断语句 若条件成立才会执行,条件不成立则语句不执行: if语句 语法一: if(条件表达式) {语句}          :true就执行,false不执行: 语法二: if(条件表达式) ...