题目链接

problem

给出一棵树,每个点有点权,每条边有边权。0号点为根,每个点的代价是这个点的点权\(\times\)该点到根路径上的边权和。

现在可以选择最多K个点。使得每个点的代价变为:这个点的点权\(\times\)改点到最近的被选中的一个祖先的边权和。

问所有点的代价和最小为多少。

solution

用\(g[i][j]\)表示以i为根的子树,强制选i,最大的贡献(这里的贡献是指比什么也不选所减少的代价。)

最终答案肯定就是初始代价-g[0][k]

考虑怎么维护出\(g\)。用\(f[i][j]\)表示以\(i\)为根的子树,\(i\)可选可不选。然后树形背包一下就可以求出g。

考虑怎么维护f。每当枚举到一个根的时候,就重新dfs一遍这棵子树,初始f[x][0]=w[x]*dep[u]。dep[u]表示从枚举的根到0号点的距离。然后同样方法背包一遍,就可以维护处\(f\)。

把j写成k调了一上午。。。。

code

/*
* @Author: wxyww
* @Date: 2019-12-21 10:08:12
* @Last Modified time: 2019-12-21 11:04:12
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 110;
ll read() {
ll x = 0,f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1; c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + c - '0'; c = getchar();
}
return x * f;
}
int siz[N],f[N][55],g[N][N],dep[N],w[N],n,K;
struct node {
int v,nxt;
}e[N];
int head[N],ejs;
void add(int u,int v) {
e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;
}
void dp(int u,int W) {
f[u][0] = W * w[u];
for(int i = head[u];i;i = e[i].nxt) {
int v = e[i].v;
dp(v,W);
for(int j = min(K,siz[u]);j >= 0;--j) {
for(int k = 0;k <= min(j,siz[v]);++k) {
f[u][j] = max(f[u][j],f[v][k] + f[u][j - k]);
}
}
}
for(int i = 1;i <= K;++i) f[u][i] = max(f[u][i],g[u][i]);//在算上强制选的答案
}
void dfs(int u) {
siz[u] = 1;
for(int i = head[u];i;i = e[i].nxt) {
dep[e[i].v] += dep[u];
dfs(e[i].v);
siz[u] += siz[e[i].v];
} g[u][1] = dep[u] * w[u]; memset(f,0,sizeof(f)); for(int i = head[u];i;i = e[i].nxt) {
int v = e[i].v;
dp(v,dep[u]);
for(int j = min(K,siz[u]);j >= 1;--j) {
for(int k = 0;k < j;++k) {
g[u][j] = max(g[u][j],g[u][j - k] + f[v][k]);
}
}
}
// if(u == 1) cout<<g[1][1]<<endl;
}
int main() {
// freopen("1.in","r",stdin);
n = read(),K = read();
++K;
for(int i = 1;i <= n;++i) {
w[i] = read();int u = read();add(u,i);
dep[i] = read();
}
dfs(0);
int ans = 0;
for(int i = 1;i <= K;++i) ans = max(ans,g[0][i]);
// cout<<g[2][1];
for(int i = 1;i <= n;++i) ans -= dep[i] * w[i];
cout<<-ans<<endl;
return 0;
}

bzoj1812 [IOI2005]riv河流的更多相关文章

  1. bzoj1812 [Ioi2005]riv

    riv 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海.这条大河的入海口处有一个村庄--名叫B ...

  2. [LUOGU] P3354 [IOI2005]Riv 河流

    题目描述 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海.这条大河的入海口处有一个村庄--名叫 ...

  3. BZOJ.1812.[IOI2005]Riv 河流(树形背包)

    BZOJ 洛谷 这个数据范围..考虑暴力一些把各种信息都记下来.不妨直接令\(f[i][j][k][0/1]\)表示当前为点\(i\),离\(i\)最近的建了伐木场的\(i\)的祖先为\(j\),\( ...

  4. P3354 [IOI2005]Riv 河流

    树形dp,设f[i][j][k]表示第i个点的子树中选择j个点作为伐木场,而且k是建了伐木场的最浅的i的祖先的情况下,最小的收益. 这种题还要练一下,咕咕 然后转移可以n4方做. // luogu-j ...

  5. BZOJ1812: [Ioi2005]riv(树形dp)

    题意 题目链接 Sol 首先一个很显然的思路是直接用\(f[i][j] / g[i][j]\)表示\(i\)的子树中选了\(j\)个节点,该节点是否选的最小权值.但是直接这样然后按照树形背包的套路转移 ...

  6. 【[IOI2005]Riv 河流】

    趁魏佬去英语演讲了,赶快%%%%%%%%%%%%%%魏佬 基本上是照着魏佬的代码写的 这其实还是一个树上背包 我们用\(dp[i][j][k]\)表示在以\(i\)为根的子树里,我们修建\(k\)个伐 ...

  7. 洛谷P3354 [IOI2005]Riv 河流——“承诺”DP

    题目:https://www.luogu.org/problemnew/show/P3354 状态中要记录一个“承诺”,只需相同承诺之间相互转移即可: 然后就是树形DP的套路了. 代码如下: #inc ...

  8. [IOI2005]Riv 河流

    https://www.zybuluo.com/ysner/note/1300088 题面 有一棵\(n\)个点的树,现在在上面放\(k\)个标记,使得每个点的权值乘上自己到最近的标记祖先的距离的和最 ...

  9. [IOI2005]Riv河流

    题目链接:洛谷,BZOJ 前置知识:莫得 题解 直接考虑dp.首先想法是设状态 \(dp[u][i]\) 表示u的子树内建 \(i\) 个伐木场且子树内木头都运到某个伐木场的最小花费.发现这样的状态是 ...

随机推荐

  1. 版本控制工具——Git常用操作

    本文引自:https://juejin.im/post/5c206f1bf265da615114c15a

  2. Dynamics CRM 2013开始推出的服务器端同步来配置邮件服务

    我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...

  3. 百度大脑UNIT3.0详解之语音语义一体化方案

    在电话客服场景里,用户和机器人交流的过程中,经常会出现沉默.打断机器人.噪声等情况,机器人在应对这些异常情况的时候,需要语音和语义理解技术进行处理,才能实现用户和机器人的流畅交谈.而这些能力的获取与应 ...

  4. SQL Server重建索引与重组索引会更新统计信息吗?

    在SQL Server中重建索引(Rebuild Index)与重组索引(Reorganize Index)会触发统计信息更新吗? 那么我们先来测试.验证一下: 我们以AdventureWorks20 ...

  5. 开启docker

    systemctl daemon-reload systemctl restart docker.service

  6. [译]Vulkan教程(23)暂存buffer

    [译]Vulkan教程(23)暂存buffer Staging buffer 暂存buffer Introduction 入门 The vertex buffer we have right now ...

  7. 使用ES6新特性async await进行异步处理

    我们往往在项目中会遇到这样的业务需求,就是首先先进行一个ajax请求,然后再进行下一个ajax请求,而下一个请求需要使用上一个请求得到的数据,请求少了还好说,如果多了,就要一层一层的嵌套,就好像有点c ...

  8. Vue 从入门到进阶之路(十一)

    之前的文章我们说了一下 vue 中组件的原生事件绑定,本章我们来所以下 vue 中的插槽使用. <!DOCTYPE html> <html lang="en"&g ...

  9. [Spring cloud 一步步实现广告系统] 10. 使用Ribbon 实现微服务调用

    在使用Ribbon调用广告投放系统API之前,我们需要先创建2个VO对象,AdPlanVO,AdPlanGetRequestVO. //数据请求对象 @Data @NoArgsConstructor ...

  10. Android 在Fragment中修改Activity中的控件

    在当前的Fragment中调用getActivity方法获取依附着的那个Activity,然后再用获取到的Activity去findViewById拿到你需要的控件对其操作就行了.