洛谷 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:

#include <cstdio>
using namespace std;
#define MAXN 3003
#define MAX(A,B) ((A)>(B)?(A):(B))
#define INF 0x3ffffff
struct e{
int w,v,nxt;
} edge[10000010]; //边数一定要开大!
int dp[MAXN][MAXN],head[MAXN],sz[MAXN];
int n,m,cnt_e;
inline void adde(int u, int v, int w){
edge[++cnt_e].w=w;
edge[cnt_e].v=v;
edge[cnt_e].nxt=head[u];
head[u]=cnt_e;
}
int solve(int x, int fa){
if(x>=n-m+1&&x<=n) //是否为用户端
return sz[x]=1;
for(register int i=head[x];i;i=edge[i].nxt){ //”递增”遍历儿子i
sz[x]+=solve(edge[i].v, x); //树形dp通常自下而上更新
for(register int j=sz[x];j>=0;--j) //枚举状态
for(register int k=0;k<=sz[edge[i].v];++k) //枚举决策,当前儿子取几个用户
dp[x][j]=MAX(dp[x][j], dp[x][j-k]+dp[edge[i].v][k]-edge[i].w);
//dp[s][i][j]=max{dp[s][i-1][j-k]+dp[w][size_w][k]-cost[s][w]} 原始状态转移方程
}
return sz[x];
}
int main() {
scanf("%d %d", &n, &m);
for(register int i=0;i<=n;i++)
for(register int j=0;j<=m;j++)
dp[i][j]=-INF;
for (int i=1;i<=n;i++) dp[i][0]=0; //注意初始化!
for(int i=1;i<=n-m;++i){
int sz;
scanf("%d", &sz);
for(int j=1;j<=sz;++j){
int a,c;
scanf("%d %d", &a, &c);
adde(i, a, c); //链式前向星建边
}
}
for(int i=n-m+1;i<=n;++i)
scanf("%d", &dp[i][1]);
solve(1,0);
for(register int i=m;i>=0;--i) //递减遍历找到第一个合法值
if(dp[1][i]>=0){
printf("%d\n", i);
break;
}
return 0;
}

需要注意:

  • 链式前向星边数不是\(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. Java 设计模式系列(七)桥接模式

    Java 设计模式系列(七)桥接模式 桥接模式(Bridge)是一种结构型设计模式.Bridge 模式基于类的最小设计原则,通过使用封装.聚合及继承等行为让不同的类承担不同的职责.它的主要特点是把抽象 ...

  2. Forms in Angular 2

    Input handling is an important part of application development. The ng-model directive provided in A ...

  3. Mybatis之整体描述

    Mybatis在我看来最大的用处就是封装了jdbc,设置参数操作和获取解析结果集.同时控制了数据库链接等操作,大部分采用了反射来映射javabean对象来进行数据库操作. 1.接下来先整体介绍下主要的 ...

  4. 矩阵乘法np.dot()及np.multiply()以及*

    转载自 https://blog.csdn.net/u012609509/article/details/70230204 Python中的几种矩阵乘法 1. 同线性代数中矩阵乘法的定义: np.do ...

  5. android studio使用真机测试时点击Debug调试模式时报Error running app:No target device found,点击运行模式却是启动正常的

    原因是adb没检测到设备(包括真机和虚拟机). 在Terminal执行adb devices命令,查看有没有连接到的设备. 如果没有设备,确认虚拟机是否正确打开,真机是否连接打开USB调试并安装驱动. ...

  6. win7搭建node+npm+bower的环境

    原文的地址:https://my.oschina.net/JeeChou/blog/219699 Windows下的NodeJS安装是比较方便的(v0.6.0版本之后,支持windows native ...

  7. MyBatis 插入主键方式和返回主键

    这使用的mysql数据库,下面这种方式(没有给mysql设置自动增长)是插入主键方式: <insert id="insertBook" parameterType=" ...

  8. Redis Quick Start [熟练版]

    一.下载解压 wget http://download.redis.io/redis-stable.tar.gztar xvzf redis-stable.tar.gzcd redis-stable ...

  9. rzdatetimepicker

    两项选为True时可显示今天和圆圈 此属性可使右边按钮下平滑 注意Format中的表示月份的MM一定要大写,不然修改时和分钟会联动.

  10. (转)JDBC模板类。

    Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDBC模板类是第一种工作模式. JdbcTempl ...