洛谷 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. 分布式理论系列(三)ZAB 协议

    分布式理论系列(三)ZAB 协议 在学习了 Paxos 后,接下来学习 Paxos 在开源软件 Zookeeper 中的应用. 一.Zookeeper Zookeeper 致力于提供一个高性能.高可用 ...

  2. 基于Web Service的客户端框架搭建四:终结篇

    前言 这是这个系列的终结篇,前面3个博客介绍了一下内容: 1.使用Http Post方式调用Web Service 2.客户端框架之数据转换层 3.客户端框架之代理层 框架结构 框架是基于C#的,在V ...

  3. SLAM拾萃(1):octomap

    前言 大家好,时隔多年之后,我又开始了博客旅程.经历了很多事情之后呢,我发现自己的想法真的很简单:好好读书做课题,闲下来时写写博客,服务大家.所以我会继续写SLAM相关的博客.如果你觉得它对你有帮助, ...

  4. zstu4273 玩具 2017-03-22 14:18 49人阅读 评论(0) 收藏

    4273: 玩具 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 700  Solved: 129 Description 商店有n个玩具,第i个玩具有 ...

  5. kali下搭建WiFi钓鱼热点

    在linux下建立无线热点并不像在windows下开启网络共享或者使用无线网卡驱动设置AP模式即可. linux下的无线共享要用到两个软件:hostapd(创建无线热点).dnsmasq(dns服务和 ...

  6. Babel 是干什么的

    首先babel是干什么的?Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行. babel就是为了支持原有的旧的环境. 一.配置文件.babelrc Babel的配置 ...

  7. Android-有序广播是可以中断的

    在之前的博客,Android-广播概念,中介绍了(广播和广播接收者)可以组件与组件之间进行通讯,有两种类型的广播(无序广播 和 有序广播),这篇博客就来讲解有序广播的代码实现: 有序广播:接收者 可以 ...

  8. 教你如何学python

    首先,你要有自信心,要明确学习目的.学Python,可以解决在软件使用中所遇到的问题,可以为找到理想工作添加重要砝码.还能锻炼思维,使我们的逻辑思维更加严密:能不断享受到创新的乐趣,将走在高科技的前沿 ...

  9. Excel2010画动态甘特图

    哈哈!你居然真的看简介点进来啦,我也想八一八Henry gantt本人的故事,可是我查了好些资料,一个槽点都没有发现,不过人生经历还是蛮拼的: 此人活了58年,前半生就是一个中规中距的机械工程师&am ...

  10. tar.gz 解压

    tar -xzvf .tar.gz tar [-cxtzjvfpPN] 文件与目录 .... 参数: -c :建立一个压缩文件的参数指令(create 的意思): -x :解开一个压缩文件的参数指令! ...