题目描述
几乎整个Byteland王国都被森林和河流所覆盖。小点的河汇聚到一起,形成了稍大点的河。就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海。这条大河的入海口处有一个村庄——名叫Bytetown。 在Byteland国,有n个伐木的村庄,这些村庄都座落在河边。目前在Bytetown,有一个巨大的伐木场,它处理着全国砍下的所有木料。木料被砍下后,顺着河流而被运到Bytetown的伐木场。Byteland的国王决定,为了减少运输木料的费用,再额外地建造k个伐木场。这k个伐木场将被建在其他村庄里。这些伐木场建造后,木料就不用都被送到Bytetown了,它们可以在运输过程中第一个碰到的新伐木场被处理。显然,如果伐木场座落的那个村子就不用再付运送木料的费用了。它们可以直接被本村的伐木场处理。 注:所有的河流都不会分叉,形成一棵树,根结点是Bytetown。 国王的大臣计算出了每个村子每年要产多少木料,你的任务是决定在哪些村子建设伐木场能获得最小的运费。其中运费的计算方法为:每一吨木料每千米1分钱。 输入输出格式
输入格式:
第一行包括两个数 n(2≤n≤100),k(1≤k≤50,且 k≤n)。n为村庄数,k为要建的伐木场的数目。除了Bytetown外,每个村子依次被命名为1,2,3……n,Bytetown被命名为0。 接下来n行,每行3个整数: wi——每年i村子产的木料的块数(0≤wi≤10000) vi——离i村子下游最近的村子(即i村子的父结点)(0≤vi≤n) di——vi到i的距离(千米)。(1≤di≤10000) 保证每年所有的木料流到bytetown的运费不超过2,000,000,000分 50%的数据中n不超过20。 输出格式:
输出最小花费,单位为分。 输入输出样例
输入样例#1:
4 2
1 0 1
1 1 10
10 2 5
1 2 3
输出样例#1:
4

树上分组背包+约定祖先

#include<iostream>
#include<cstdio>
using namespace std; inline int rd() {
int ret=0,f=1;
char c;
while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
while(isdigit(c))ret=ret*10+c-'0',c=getchar();
return ret*f;
} const int MAXN=155; struct Edge {
int next,to,w;
} e[MAXN];
int ecnt,head[MAXN];
inline void add(int x,int y,int w) {
e[++ecnt].next = head[x];
e[ecnt].to = y;
e[ecnt].w = w;
head[x] = ecnt;
} int n,k;
int val[MAXN];
int f[MAXN][MAXN][MAXN];
int g[MAXN][MAXN][MAXN];
int stack[MAXN],top;
int dep[MAXN]; void dfs(int x) {
stack[++top]=x;
for(int i=head[x]; i; i=e[i].next) {
int v=e[i].to;
dep[v]=dep[x]+e[i].w;
dfs(v);
for(int fa=1; fa<=top; fa++) {
for(int j=k; j>=0; j--) {
f[x][j][stack[fa]]+=f[v][0][stack[fa]];
g[x][j][stack[fa]]+=f[v][0][x];
for(int u=0; u<=j; u++) {//
f[x][j][stack[fa]]=min(f[x][j][stack[fa]],f[x][j-u][stack[fa]]+f[v][u][stack[fa]]);
g[x][j][stack[fa]]=min(g[x][j][stack[fa]],g[x][j-u][stack[fa]]+f[v][u][x]);
}
}
}
}
for(int fa=1; fa<=top; fa++) {
for(int j=0; j<=k; j++) {
if(j>=1) f[x][j][stack[fa]]=min(f[x][j][stack[fa]]+val[x]*(dep[x]-dep[stack[fa]]),g[x][j-1][stack[fa]]);
else f[x][j][stack[fa]]+=val[x]*(dep[x]-dep[stack[fa]]);
}
} top--;
} int main() {
n=rd();
k=rd();
for(int i=1; i<=n; i++) {
int y,w;
val[i]=rd();
y=rd();
w=rd();
add(y,i,w);
}
dfs(0);
cout<<f[0][k][0];
return 0;
}

[LUOGU] P3354 [IOI2005]Riv 河流的更多相关文章

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

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

  2. P3354 [IOI2005]Riv 河流

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

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

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

  4. 【[IOI2005]Riv 河流】

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

  5. [IOI2005]Riv 河流

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

  6. bzoj1812 [IOI2005]riv河流

    题目链接 problem 给出一棵树,每个点有点权,每条边有边权.0号点为根,每个点的代价是这个点的点权\(\times\)该点到根路径上的边权和. 现在可以选择最多K个点.使得每个点的代价变为:这个 ...

  7. [IOI2005]Riv河流

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

  8. BZOJ 1812: [Ioi2005]riv( 树形dp )

    树背包, 左儿子右兄弟来表示树, dp(x, y, z)表示结点x, x的子树及x的部分兄弟共建y个伐木场, 离x最近的伐木场是z时的最小代价. 时间复杂度O(N^2*K^2) ----------- ...

  9. 1812: [Ioi2005]riv

    1812: [Ioi2005]riv Time Limit: 10 Sec Memory Limit: 64 MB Submit: 635 Solved: 388 [Submit][Status][D ...

随机推荐

  1. asp.net mvc5 使用百度ueditor 本编辑器完整示例(三)在IIS中多个应用程序使用多个ueditor对象

    最近做了一个项目,要求同一类型的多个专业应用程序(网站),但是每个应用程序都需要调用各自当中的ueditor. 步骤: 一.在vs2013中设置每个专业的asp.net mvc 应用程序. 1.配置根 ...

  2. Pascal之工种问题

    program Project2; Type ma=(A,B,C); wk=..; const x:array[ma,wk] of integer =((,,),(,,),(,,)); var max ...

  3. Linux下 本地yum源搭建

    第1章 关于yum源 1.1 什么是yum源 yum(Yellow dog Updater, Modified)是一个在 Fedora 和 RedHat 以及 CentOS 中的 Shell 前端软件 ...

  4. git基本操作(入门)

    下面以一个最简单的开发过程,呈现git最基本的操作命令 1.下载代码(以code命名仓库为例) git clone xxxxx/code.git cd code 2.查看所有分支 git branch ...

  5. python之logging模块简单用法

    前言: python引入logging模块,用来记录自己想要的信息.print也可以输入日志,但是logging相对print来说更好控制输出在哪个地方.怎么输出以及控制消息级别来过滤掉那些不需要的信 ...

  6. Drawable新属性

    mSelectEndorseReasonTv.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.toup, 0);新属性替换: Draw ...

  7. not and or

    not and or (逻辑表达式) 首先要做一些准备知识: 1,优先级:逻辑型 < 测试型 < 关系型 < 算数型 2,逻辑型优先级:or < and < not 3, ...

  8. linux系统资源限制ulimit

    ulimit命令用来限制系统用户对shell资源的访问.如果不懂什么意思,下面一段内容可以帮助你理解: 假设有这样一种情况,当一台 Linux 主机上同时登陆了 10 个人,在系统资源无限制的情况下, ...

  9. 暑期训练狂刷系列——poj 3264 Balanced Lineup(线段树)

    题目连接: http://poj.org/problem?id=3264 题目大意: 有n个数从1开始编号,问在指定区间内,最大数与最小数的差值是多少? 解题思路: 在节点中存储max,min,然后查 ...

  10. Monkey Banana Problem LightOJ - 1004

    Monkey Banana Problem LightOJ - 1004 错误记录: 1.数组开小2.每组数据数组没有清空 #include<cstdio> #include<cst ...