bzoj1812 [IOI2005]riv河流
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河流的更多相关文章
- bzoj1812 [Ioi2005]riv
riv 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海.这条大河的入海口处有一个村庄--名叫B ...
- [LUOGU] P3354 [IOI2005]Riv 河流
题目描述 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海.这条大河的入海口处有一个村庄--名叫 ...
- BZOJ.1812.[IOI2005]Riv 河流(树形背包)
BZOJ 洛谷 这个数据范围..考虑暴力一些把各种信息都记下来.不妨直接令\(f[i][j][k][0/1]\)表示当前为点\(i\),离\(i\)最近的建了伐木场的\(i\)的祖先为\(j\),\( ...
- P3354 [IOI2005]Riv 河流
树形dp,设f[i][j][k]表示第i个点的子树中选择j个点作为伐木场,而且k是建了伐木场的最浅的i的祖先的情况下,最小的收益. 这种题还要练一下,咕咕 然后转移可以n4方做. // luogu-j ...
- BZOJ1812: [Ioi2005]riv(树形dp)
题意 题目链接 Sol 首先一个很显然的思路是直接用\(f[i][j] / g[i][j]\)表示\(i\)的子树中选了\(j\)个节点,该节点是否选的最小权值.但是直接这样然后按照树形背包的套路转移 ...
- 【[IOI2005]Riv 河流】
趁魏佬去英语演讲了,赶快%%%%%%%%%%%%%%魏佬 基本上是照着魏佬的代码写的 这其实还是一个树上背包 我们用\(dp[i][j][k]\)表示在以\(i\)为根的子树里,我们修建\(k\)个伐 ...
- 洛谷P3354 [IOI2005]Riv 河流——“承诺”DP
题目:https://www.luogu.org/problemnew/show/P3354 状态中要记录一个“承诺”,只需相同承诺之间相互转移即可: 然后就是树形DP的套路了. 代码如下: #inc ...
- [IOI2005]Riv 河流
https://www.zybuluo.com/ysner/note/1300088 题面 有一棵\(n\)个点的树,现在在上面放\(k\)个标记,使得每个点的权值乘上自己到最近的标记祖先的距离的和最 ...
- [IOI2005]Riv河流
题目链接:洛谷,BZOJ 前置知识:莫得 题解 直接考虑dp.首先想法是设状态 \(dp[u][i]\) 表示u的子树内建 \(i\) 个伐木场且子树内木头都运到某个伐木场的最小花费.发现这样的状态是 ...
随机推荐
- asp.net允许跨域配置web.config
<configuration> <system.webServer> <modules> <add name="CultureAwareHttpMo ...
- IS:Introduction Parrot
Ax_What is Linux? "Linux is a family of free and open-source software operating systems based o ...
- 【实习第十天】odoo开发基础整合
前言 发文时间是2019年7月19日.提一下学习odoo的感受,odoo目前在国内并不是很流行,且主流是在企业型软件,所以导致目前odoo在网上的文献很少,学习相对来说比其他框架吃力.以下为大家总结1 ...
- Java学习笔记--线程day01
线程的概念:一个线程是进程的顺序执行流: 同类的多个线程共享一块内存空间和一组系统资源,线程本身有一个供程序执行时的堆栈.线程在切换时负荷小,因此,线程也被称为轻负荷进程.一个进程中可以有多个线程. ...
- 使用Active Database Duplication创建跨平台Data Guard设置 (Windows/Linux) (Doc ID 881421.1)
Using Active Database Duplication to Create Cross Platform Data Guard Setup (Windows/Linux) (Doc ID ...
- Python语法速查: 7. 函数基础
返回目录 (1)函数基本 ● 函数是第一类对象 Python中万物皆对象,所有对象都是第一类的(first class),函数也不例外,也是第一类对象.既然是对象,那就可以当作普通的对象数据处理,比如 ...
- 使用ClickOnce发布Windows应用程序
前言 因本人工作需要,在一名非常非常好的老师的指导下,入门了C#,再次向老师表示感谢. 本人平时经常遇到的业务就是将数据下发给各部门,并让各部门再上报,此过程中经常会遇到数据格式不正确,数据错误等诸多 ...
- element form 对单个字段做验证
this.$refs[formName].validateField('phone', phoneError => { //验证手机号码是否正确 if (!phoneError) { conso ...
- kettle抽取数据发送邮件Linux调度
kettle抽取数据发送邮件Linux调度 #1.进入kettle安装目录 然后执行sqoop.sh文件启动kettlecd /app/pdi-ce-7.1.0.0-12/data-integrati ...
- HBase删除数据的原理
转自:https://blog.csdn.net/cenjianteng/article/details/96645447 -------------------------------------- ...