riv

几乎整个Byteland王国都被森林和河流所覆盖。小点的河汇聚到一起,形成了稍大点的河。就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海。这条大河的入海口处有一个村庄——名叫Bytetown 在Byteland国,有n个伐木的村庄,这些村庄都座落在河边。目前在Bytetown,有一个巨大的伐木场,它处理着全国砍下的所有木料。木料被砍下后,顺着河流而被运到Bytetown的伐木场。Byteland的国王决定,为了减少运输木料的费用,再额外地建造k个伐木场。这k个伐木场将被建在其他村庄里。这些伐木场建造后,木料就不用都被送到Bytetown了,它们可以在 运输过程中第一个碰到的新伐木场被处理。显然,如果伐木场座落的那个村子就不用再付运送木料的费用了。它们可以直接被本村的伐木场处理。 注意:所有的河流都不会分叉,也就是说,每一个村子,顺流而下都只有一条路——到bytetown。 国王的大臣计算出了每个村子每年要产多少木料,你的任务是决定在哪些村子建设伐木场能获得最小的运费。其中运费的计算方法为:每一块木料每千米1分钱。 编一个程序: 1.从文件读入村子的个数,另外要建设的伐木场的数目,每年每个村子产的木料的块数以及河流的描述。 2.计算最小的运费并输出。Input第一行 包括两个数 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村子下游最近的村子(或bytetown)(0<=vi<=n) di——vi到i的距离(km)。(1<=di<=10000) 保证每年所有的木料流到bytetown的运费不超过2000,000,000分 50%的数据中n不超过20。Output输出最小花费,精确到分。Sample Input

4 2
1 0 1
1 1 10
10 2 5
1 2 3

Sample Output

4

题解:

先搞出g[i][j]表示i到j的运输花费,只是单个点,将f[i][i][0]先处理好,这个应该比较容易吧,

还有处理处f[i][fa[i]][0]的初始值,每一个父亲,就是整条链上所有父亲,什么意思,就是

一层一层更新上去。

处理出来的作为树形dp的初始化,然后就是dp

h1[k]表示在该点,建k个,该点建,的最小花费。

h2[k]表示在该点,建k个,该点不建,最小花费。

然后就dp在哪个子孙建多少个,的一个背包dp。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cstdlib>
#define N 107
#define M 57
using namespace std; int n,k;
int cnt,head[N],next[N*],rea[N*];
int fa[N],w[N],di[N],g[N][N];
int f[N][N][M];
bool vis[N][N][M]; void add(int u,int v){next[++cnt]=head[u],head[u]=cnt,rea[cnt]=v;}
void dfs_init(int u)
{
int t=u;
while(fa[t]>=)
{
g[u][fa[t]]=g[u][t]+w[u]*di[t];
t=fa[t];
}
t=u;
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
dfs_init(v);
w[u]+=w[v];
f[u][u][]+=f[v][u][];
}
vis[u][t][]=;
while(fa[t]>=)
{
vis[u][fa[t]][]=;
f[u][fa[t]][]=f[u][t][]+w[u]*di[t];
t=fa[t];
}
}
int solve_dp(int u,int now,int k)
{
if (vis[u][now][k]) return f[u][now][k];
vis[u][now][k]=;
int h1[],h2[];
memset(h1,,sizeof(h1));
for (int i=;i<=k;i++)
h2[i]=g[u][now];
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
for (int j=k;j>=;j--)
{
h1[j]+=solve_dp(v,u,);
h2[j]+=solve_dp(v,now,);
for (int t=;t<=j;t++)
{
h1[j]=min(h1[j],h1[j-t]+solve_dp(v,u,t));
h2[j]=min(h2[j],h2[j-t]+solve_dp(v,now,t));
}
}
}
f[u][now][k]=min(h1[k-],h2[k]);
return f[u][now][k];
}
int main()
{
memset(head,-,sizeof(head));
scanf("%d%d",&n,&k);
for (int i=;i<=n;i++)
{
scanf("%d%d%d",&w[i],&fa[i],&di[i]);
add(fa[i],i);
}
fa[]=-;
dfs_init();
printf("%d\n",solve_dp(,,k));
}
												

bzoj1812 [Ioi2005]riv的更多相关文章

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

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

  2. bzoj1812 [IOI2005]riv河流

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

  3. 【BZOJ1812】[Ioi2005]riv 树形DP

    [BZOJ1812][Ioi2005]riv Description 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河, ...

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

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

  5. 1812: [Ioi2005]riv

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

  6. 【BZOJ1812】riv(多叉树转二叉树,树形DP)

    题意:给定一棵树,每个点有权值,每条边有边权(单向边).你可以选取K个黑点,使得从每个点移动到距离他最近的黑点的花费(距离*点权)的总和最小. n<=100 k<=50 w[i],a[i] ...

  7. BZOJ1812 [IOI2005]river

    传送门: 很常规的一道树规,转为左儿子右兄弟. 然后$f[node][anc][K]$表示在node节点上,最近的有贡献祖先在anc上,在node的儿子和兄弟上有k个有贡献节点的最优值. 然后得出以下 ...

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

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

  9. P3354 [IOI2005]Riv 河流

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

随机推荐

  1. 201521123017 《Java程序设计》第8周学习总结

    1. 本周学习总结 2. 书面作业 Q1.List中指定元素的删除(题目4-1) 1.1 实验总结 for (int i = list.size()-1; i >=0; i--) {//从最后一 ...

  2. 201521123099 《Java程序设计》第2周学习总结

    1. 本周学习总结 1.Java对我来说难度还是很大.需要花更多时间去学习. 2. 书面作业 1.使用Eclipse关联jdk源代码,并查看String对象的源代码(截图)?分析String使用什么来 ...

  3. Python[小甲鱼003小插曲之变量和字符串]

      >>>teacher = 3 >>>teacher  3 #在定义了一个变量后可以之间输入整个变量即可访问这个变量.   >>> teache ...

  4. 201521123036 《Java程序设计》第11周学习总结

    本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 书面作业 本次PTA作业题集多线程 互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1.1 除了使用 ...

  5. 201521123013 《Java程序设计》第12周学习总结

    1. 本章学习总结 2. 书面作业 将Student对象(属性:int id, String name,int age,double grade)写入文件student.data.从文件读出显示. Q ...

  6. 201521123089 《Java程序设计》第13周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 1.协议:网络中为了进行数据交换而建立的原则,标准或约定. 2.域名:Internet上某一台计算机的名称 ...

  7. 超简单的js评价小星星

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. 我和Python

    记不得是年,我在网易云课堂上乱逛,看到了哈佛大学的<计算机编程导论>,这门课讲的正好是Python,讲的啥内容已经记不得多少了,因为是全英文教学,我只能慢慢的看字幕,一集得看个好几遍. 我 ...

  9. TestNG操作详解

    运行测试步骤方法有如下两种: 1. 直接在Eclipse运行testNG的测试用例, 在代码编辑区域鼠标右键, 选择Run as ->testNG Test 2. 在工程的根目录下, 建立tes ...

  10. JVM(四)内存回收(二)

    在上一节中"JVM(三)内存回收(一)"我讲到了垃圾回收的几种算法,算是解决了之前提到的3个问题中的最后一个. 关于内存回收,还应该了解常用的内存回收器(GC Collector) ...