题目描述

几乎整个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

这道题因为村庄呈树形结构,所以选用树形DP。

自底向上更新答案,dp[x][j][k][0/1] 代表在第x节点处,离x最近的祖先伐木场为j,用了k个伐木场,x节点有/无伐木场的最小花费。先dfs遍历树,开一个stack数组记录每个节点到根节点的距离。之后开始枚举j与k与子树伐木场个数,更新答案。

  1. #include<iostream>
  2. #include<cstdio>
  3. using namespace std;
  4. typedef long long LL;
  5. const int MAXN = 105;
  6. struct Edge{
  7. int nxt,to,val;
  8. }edge[MAXN*2];
  9. //size为stack中元素个数,stack记录子节点,d记录深度。
  10. int n,K,w[MAXN],size,stack[MAXN],d[MAXN];
  11. int head[MAXN],cnt;
  12. LL dp[MAXN][MAXN][MAXN][2];
  13. inline void add(int bg,int ed,int ww){
  14. edge[++cnt].to=ed;
  15. edge[cnt].val=ww;
  16. edge[cnt].nxt=head[bg];
  17. head[bg]=cnt;
  18. }
  19. inline void dfs(int u){
  20. stack[++size]=u;
  21. for(register int i=head[u];i;i=edge[i].nxt){
  22. int v=edge[i].to; //枚举子节点。
  23. d[v]=d[u]+edge[i].val; //更新子节点距离。
  24. dfs(v);
  25. for(int j=1;j<=size;j++) //枚举祖先。
  26. for(int k=K;k>=0;k--){ //枚举u及子树的伐木场个数。
  27. dp[u][stack[j]][k][0]+=dp[v][stack[j]][0][0];
  28. dp[u][stack[j]][k][1]+=dp[v][u][0][0];
  29. //子节点不建。
  30. for(int x=0;x<=k;x++){ //枚举子节点建的伐木场数。
  31. dp[u][stack[j]][k][0]=min(dp[u][stack[j]][k-x][0]
  32. +dp[v][stack[j]][x][0],dp[u][stack[j]][k][0]);
  33. dp[u][stack[j]][k][1]=min(dp[u][stack[j]][k][1]
  34. ,dp[u][stack[j]][k-x][1]+dp[v][u][x][0]);
  35. }
  36. }
  37. }
  38. for(register int j=1;j<=size;j++)
  39. for(register int k=0;k<=K;k++){
  40. if(k>=1){
  41. dp[u][stack[j]][k][0]=min(dp[u][stack[j]][k][0]
  42. +w[u]*(d[u]-d[stack[j]]),dp[u][stack[j]][k-1][1]);
  43. }
  44. else
  45. dp[u][stack[j]][k][0]+=w[u]*(d[u]-d[stack[j]]);
  46. }
  47. //将dp[][][][0]与dp[][][][1]合并。
  48. size--;
  49. }
  50. int main(){
  51. scanf("%d%d",&n,&K);
  52. for(register int i=1;i<=n;i++){
  53. int fa,ww;
  54. scanf("%d%d%d",&w[i],&fa,&ww);
  55. add(fa,i,ww);
  56. }
  57. dfs(0);
  58. printf("%lld",dp[0][0][K][0]);
  59. return 0;
  60. }

IOI 2005 River (洛谷 3354)的更多相关文章

  1. 洛谷3354(IOI2005)河流——“承诺”

    题目:https://www.luogu.org/problemnew/show/P3354 虽说是几个月前曾经讲过的题,但没有题解而自己(花了两个多小时)A了好高兴!!! 这是一个很好的套路:“承诺 ...

  2. bzoj 2005 & 洛谷 P1447 [ Noi 2010 ] 能量采集 —— 容斥 / 莫比乌斯反演

    题目:bzoj 2005 https://www.lydsy.com/JudgeOnline/problem.php?id=2005   洛谷 P1447 https://www.luogu.org/ ...

  3. 【洛谷2904/BZOJ1617】[USACO08MAR]跨河River Crossing(动态规划)

    题目:洛谷2904 分析: 裸dp-- dp方程也不难想: \(dp[i]\)表示运\(i\)头牛需要的最短时间,\(sum[i]\)表示一次运\(i\)头牛(往返)所需的时间,则 \[dp[i]=m ...

  4. 洛谷P1052 过河

    P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上. 由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青 ...

  5. 关于三目运算符与if语句的效率与洛谷P2704题解

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...

  6. 【洛谷】P1052 过河【DP+路径压缩】

    P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙 ...

  7. 【题解】洛谷P1350 车的放置(矩阵公式推导)

    洛谷P1350:https://www.luogu.org/problemnew/show/P1350 思路 把矩阵分为上下两块N与M 放在N中的有i辆车 则放在M中有k-i辆车 N的长为a   宽为 ...

  8. 【题解】洛谷P2822 [NOIP2016TG ]组合数问题 (二维前缀和+组合数)

    洛谷P2822:https://www.luogu.org/problemnew/show/P2822 思路 由于n和m都多达2000 所以暴力肯定是会WA的 因为整个组合数是不会变的 所以我们想到存 ...

  9. 洛谷 2216 [HAOI2007]理想的正方形

    题目戳这里 一句话题意 给你一个a×b的矩形,求一个n×n的子矩阵,矩阵里面的最大值和最小值之差最小. Solution 这个题目许多大佬都是单调队列,但是我不是很会,只好用了比较傻逼的方法: 首先我 ...

随机推荐

  1. 如何在webpack中使用loader

    一.什么是loader loader 用于对模块的源代码进行转换.loader 可以使你在 import 或"加载"模块时预处理文件.因此,loader 类似于其他构建工具中“任务 ...

  2. leetcode-12双周赛-1246-删除回文子数组

    题目描述: 方法:区间dp O(N^3) class Solution: def minimumMoves(self, A: List[int]) -> int: N = len(A) dp = ...

  3. Cross platform

    值得学习的C/C++语言开源项目 (1)ACE 庞大.复杂,适合大型项目.开源.免费,不依赖第三方库,支持跨平台. http://www.cs.wustl.edu/~schmidt/ACE.html ...

  4. delphi TTcpClient TTcpServer分析(转)

    delphi TTcpClient TTcpServer分析(转) 只描述windows socket部分. sockets.pas中各个类得继承关系: TBaseSocket | --------- ...

  5. CentOS 7.2 安装MySQL 5.7

    CentOS 7之后的版本yum的默认源中使用MariaDB替代原先MySQL,因此安装方式较为以往有一些改变: 下载mysql的源 wget http://dev.mysql.com/get/mys ...

  6. Robot Framework:数据库操作

    robotframework 操作数据库,需要安装DatabaseLibrary库 pip install robotframework-databaselibrary Python操作不同的数据库, ...

  7. 【纪中集训】2019.07.11【NOIP提高组】模拟 B 组TJ

    Preface 今天的B组题确实比A组难多了... T1 Description 有一个长为\(n(n\in[1,2*10^5])\)的01串,有\(m(m\in[1,10^5])\)个限制\(a_i ...

  8. Vue源码------------- 数据响应系统的基本思路

    在 Vue 中,我们可以使用 $watch 观测一个字段,当字段的值发生变化的时候执行指定的观察者,如下: var vm = new Vue({ data: { num:1 } }) vm.$watc ...

  9. MFC弹出选择文件和选择文件夹代码

    选择文件夹 TCHAR szSelectedDir[]; BROWSEINFO bi; ITEMIDLIST *il; bi.hwndOwner = m_hWnd; bi.pidlRoot = NUL ...

  10. contest20191023

    slz的题 KCN 雨中的晴天 宫水三叶生活的城市是一个一维平面上的城市.三叶喜欢用一个长度为n的线段来表示这座城市.线段上(包含端点)平均分布着 $n+1$ 个点,其中第 $i$ 个点到第 $i+1 ...