洛谷 P1273 有线电视网(树形背包)

干透一道题

题面:洛谷 P1273

本质就是个背包。这道题dp有点奇怪,最终答案并不是dp值,而是最后遍历寻找那个合法且最优的\(i\)作为答案。dp值存的是当前状态下的成本,所以合法情况即当成本值大于等于0,不亏本的时候。

因为dp维护的是成本,并且按照背包思想,存在让这个用户接入和不让这个用户接入两种决策,类比背包,所以状态转移方程容易得到原始方程:

\[dp[s][i][j]=max \{ dp[s][i-1][j-k]+dp[w][size_w][k]-cost[s][w](w \in son[s]) \}
\]

\(dp[s][i][j]\)表示当前节点\(s\)的前\(i\)个儿子中选取\(j\)个用户的成本,决策当前儿子接入\(k\)个用户。但是这里我们可以像01背包那样优化一维\(i\),只要我们递增遍历\(i\),递减遍历\(j\)即可,因为这样\(i-1\)轮的\(dp[s][i-1][j-k]\)状态才没有被第\(i\)轮的\(dp[s][i][j-k]\)状态覆盖,并且\(dp[w][k]\)最终的值就是\(dp[w][size_w][k]\)。

最终二维的dp方程:

\[dp[s][j]=max \{ dp[s][j-k]+dp[w][k]-cost[s][w](w \in son[s]) \}
\]

192ms AC Code:

  1. #include <cstdio>
  2. using namespace std;
  3. #define MAXN 3003
  4. #define MAX(A,B) ((A)>(B)?(A):(B))
  5. #define INF 0x3ffffff
  6. struct e{
  7. int w,v,nxt;
  8. } edge[10000010]; //边数一定要开大!
  9. int dp[MAXN][MAXN],head[MAXN],sz[MAXN];
  10. int n,m,cnt_e;
  11. inline void adde(int u, int v, int w){
  12. edge[++cnt_e].w=w;
  13. edge[cnt_e].v=v;
  14. edge[cnt_e].nxt=head[u];
  15. head[u]=cnt_e;
  16. }
  17. int solve(int x, int fa){
  18. if(x>=n-m+1&&x<=n) //是否为用户端
  19. return sz[x]=1;
  20. for(register int i=head[x];i;i=edge[i].nxt){ //”递增”遍历儿子i
  21. sz[x]+=solve(edge[i].v, x); //树形dp通常自下而上更新
  22. for(register int j=sz[x];j>=0;--j) //枚举状态
  23. for(register int k=0;k<=sz[edge[i].v];++k) //枚举决策,当前儿子取几个用户
  24. dp[x][j]=MAX(dp[x][j], dp[x][j-k]+dp[edge[i].v][k]-edge[i].w);
  25. //dp[s][i][j]=max{dp[s][i-1][j-k]+dp[w][size_w][k]-cost[s][w]} 原始状态转移方程
  26. }
  27. return sz[x];
  28. }
  29. int main() {
  30. scanf("%d %d", &n, &m);
  31. for(register int i=0;i<=n;i++)
  32. for(register int j=0;j<=m;j++)
  33. dp[i][j]=-INF;
  34. for (int i=1;i<=n;i++) dp[i][0]=0; //注意初始化!
  35. for(int i=1;i<=n-m;++i){
  36. int sz;
  37. scanf("%d", &sz);
  38. for(int j=1;j<=sz;++j){
  39. int a,c;
  40. scanf("%d %d", &a, &c);
  41. adde(i, a, c); //链式前向星建边
  42. }
  43. }
  44. for(int i=n-m+1;i<=n;++i)
  45. scanf("%d", &dp[i][1]);
  46. solve(1,0);
  47. for(register int i=m;i>=0;--i) //递减遍历找到第一个合法值
  48. if(dp[1][i]>=0){
  49. printf("%d\n", i);
  50. break;
  51. }
  52. return 0;
  53. }

需要注意:

  • 链式前向星边数不是\(N\),一定要开大
  • dp的遍历顺序一定要正确,因为你已经优化了一维\(i\)
  • 用户端支付的钱\(w\)应该表示为\(dp[n][1]=w\)
  • dp一定要结合dp方程初始化

洛谷 P1273 有线电视网(树形背包)的更多相关文章

  1. 洛谷P1273 有线电视网 (树上分组背包)

    洛谷P1273 有线电视网 题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节 ...

  2. 洛谷 P1273 有线电视网

    2016-05-31 13:25:45 题目链接: 洛谷 P1273 有线电视网 题目大意: 在一棵给定的带权树上取尽量多的叶子节点,使得sigma(val[选择的叶子节点])-sigma(cost[ ...

  3. 【题解】洛谷P1273 有线电视网(树上分组背包)

    次元传送门:洛谷P1273 思路 一开始想的是普通树形DP 但是好像实现不大好 观摩了一下题解 是树上分组背包 设f[i][j]为以i为根的子树中取j个客户得到的总价值 我们可以以i为根有j组 在每一 ...

  4. 洛谷P1273 有线电视网 树上分组背包DP

    P1273 有线电视网 )逼着自己写DP 题意:在一棵树上选出最多的叶子节点,使得叶子节点的值 减去 各个叶子节点到根节点的消耗 >= 0: 思路: 树上分组背包DP,设dp[u][k] 表示 ...

  5. 洛谷——P1273 有线电视网

    P1273 有线电视网 题目大意: 题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树 ...

  6. C++ 洛谷 P1273 有线电视网 题解

     P1273 有线电视网  很明显,这是一道树形DP(图都画出来了,还不明显吗?) 未做完,持续更新中…… #include<cstdio> #include<cstring> ...

  7. 洛谷P1273 有线电视网 【树上分组背包】

    题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从转播站到转播站以及从 ...

  8. [洛谷P1273] 有线电视网

    类型:树形背包 传送门:>Here< 题意:给出一棵树,根节点在转播足球赛,每个叶子节点是一个观众在收看.每个叶子结点到根节点的路径权值之和是该点转播的费用,每个叶子节点的观众都会付val ...

  9. 洛谷 P1273 有线电视网 题解

    题面 按照常见树形背包定义状态:设dp[u][j]表示在以u为根的子树中,选择j个客户所能获得的最大收益. 状态转移:dp[u][j]=max(dp[u][j-k],dp[v][k]-w(u,v)); ...

随机推荐

  1. SFTP 安装与配置

    SFTP 安装与配置 sftp 是 Secure File Transfer Protocol 的缩写,安全文件传送协议.可以为传输文件提供一种安全的加密方法.SFTP 为 SSH 的一部分,由于这种 ...

  2. 让Ubuntu使用阿里云国内源,解决下载速度慢问题。

    阿里云镜像官方地址 http://mirrors.aliyun.com/ 找到最新源地址列表: http://www.linuxdiyf.com/linux/23163.html 软件包管理中心(推荐 ...

  3. iOS密码输入框的实现

    [iOS密码输入框的实现] 就是一个UITextField,把属性 UITextField.secureTextEntry设置为Yes即可.此种UI效果为iOS默认效果.

  4. .NET基础 (16)事件

    事件1 请解释事件的基本使用方法2 事件和委托有何联系3 如何设计一个带有很多事件的类型4 用代码表示如下情景:猫叫.老鼠逃跑.主人惊醒 事件1 请解释事件的基本使用方法 事件时一种使对象或类能够提供 ...

  5. RSA加密解密总结

    简单的控制台程序 #include"stdafx.h" #include <math.h> #include<string.h> /*/求解密密钥d的函数( ...

  6. 监控小工具(jconsole)

    偶然发现的一个监控小工具 配置好Jmeter运行的环境,在CMD命令中输入:jconsole 即可弹出一个[java监视和管理控制台]

  7. ZOJ2256 Mincost 2017-04-16 19:36 44人阅读 评论(0) 收藏

    Mincost Time Limit: 2 Seconds      Memory Limit: 65536 KB The cost of taking a taxi in Hangzhou is n ...

  8. 试题 C: 数列求值 蓝桥杯

    试题 C: 数列求值本题总分: 10 分[问题描述]给定数列 1, 1, 1, 3, 5, 9, 17, …,从第 4 项开始,每项都是前 3 项的和.求第 20190324 项的最后 4 位数字.[ ...

  9. Android-Sqlite-OOP方式操作增删改查

    之前写的数据库增删改查,是使用SQL语句来实现的,Google 就为Android开发人员考虑,就算不会SQL语句也能实现增删改查,所以就有了OOP面向对象的增删改查方式 其实这种OOP面向对象的增删 ...

  10. Easy mistakes in c#

    ACCESS MODIFIERS c# has some access modifiers as below: public:class or member can be accessed by no ...