【洛谷P1273】有线电视网
题目大意:给定一棵 N 个节点的有根树,1 号节点为根节点,叶子节点有点权,每条边有边权,每经过一条边都减去该边权,每经过一个节点都加上该点权,求在保证权值和为非负数的前提下最多能经过多少个叶子节点。
题解:\(dp[u][i]\) 表示在以 u 为根节点的子树中,经过 i 个叶子节点的最大权值和,则有状态转移方程:$$dp[u][i]=max(dp[u][i],dp[v][k]+dp[u][i-k])$$。
一般前提为第一要素,作为要最优化的值,将要求的最优化的值最为附加属性,最后在满足前提的条件下遍历附加属性求出答案。
update on 2019.5.24
学习到了树上背包问题的上下界优化。
一开始做这道题肯定会觉得复杂度分析很奇怪,即:三个 for 循环竟然过了3000的数据量。
最后看了大佬的博客终于明白了,复杂度从严格意义上来说就是 \(O(n^2)\) 的。
感性证明如下:
我们实现的 dfs 过程可以看作是子树维护的信息合并的过程。在这个过程中,发现任意两个点为根节点的子树信息均发生且仅发生了一次合并。而对于任意两个点的信息合并仅发生在这两个节点的 lca 处,因此时间复杂度为 \(O(n^2)\)。
稍微严谨一点的证明如下:
\]
首先证明对于子树合并的过程复杂度是 \(O(sz[u]^2)\) :
\]
再证明前面子树的和式也是 \(O(sz[u]^2)\):
利用数学归纳法可知,每个子树都是 \(O(sz[v]^2)\) 的,那么在合并的过程中,利用均值不等式(平方的和大于和的平方)可直接证出。
因此,总的时间复杂度为 \(O(n^2)\)。
代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn=3010;
struct node{
int nxt,to,w;
}e[maxn<<1];
int tot,head[maxn];
inline void add_edge(int from,int to,int w){
e[++tot]=node{head[from],to,w},head[from]=tot;
}
int n,m,val[maxn],dp[maxn][maxn];
void read_and_parse(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n-m;i++){
int k;scanf("%d",&k);
for(int j=1;j<=k;j++){
int to,w;scanf("%d%d",&to,&w);
add_edge(i,to,w);
}
}
for(int i=n-m+1;i<=n;i++)scanf("%d",&val[i]);
memset(dp,0xcf,sizeof(dp));
}
int dfs(int u){
dp[u][0]=0;
if(u>n-m){dp[u][1]=val[u];return 1;}
int sum=0;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
int t=dfs(v);sum+=t;
for(int j=sum;j;j--)
for(int k=1;k<=t;k++)
dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]-e[i].w);
}
return sum;
}
void solve(){
dfs(1);
int ans=0;
for(int i=m;i;i--)if(dp[1][i]>=0){ans=i;break;}
printf("%d\n",ans);
}
int main(){
read_and_parse();
solve();
return 0;
}
【洛谷P1273】有线电视网的更多相关文章
- 洛谷 P1273 有线电视网
2016-05-31 13:25:45 题目链接: 洛谷 P1273 有线电视网 题目大意: 在一棵给定的带权树上取尽量多的叶子节点,使得sigma(val[选择的叶子节点])-sigma(cost[ ...
- 洛谷 P1273 有线电视网(树形背包)
洛谷 P1273 有线电视网(树形背包) 干透一道题 题面:洛谷 P1273 本质就是个背包.这道题dp有点奇怪,最终答案并不是dp值,而是最后遍历寻找那个合法且最优的\(i\)作为答案.dp值存的是 ...
- 洛谷P1273 有线电视网 (树上分组背包)
洛谷P1273 有线电视网 题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节 ...
- 【题解】洛谷P1273 有线电视网(树上分组背包)
次元传送门:洛谷P1273 思路 一开始想的是普通树形DP 但是好像实现不大好 观摩了一下题解 是树上分组背包 设f[i][j]为以i为根的子树中取j个客户得到的总价值 我们可以以i为根有j组 在每一 ...
- 洛谷——P1273 有线电视网
P1273 有线电视网 题目大意: 题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树 ...
- C++ 洛谷 P1273 有线电视网 题解
P1273 有线电视网 很明显,这是一道树形DP(图都画出来了,还不明显吗?) 未做完,持续更新中…… #include<cstdio> #include<cstring> ...
- 洛谷P1273 有线电视网 树上分组背包DP
P1273 有线电视网 )逼着自己写DP 题意:在一棵树上选出最多的叶子节点,使得叶子节点的值 减去 各个叶子节点到根节点的消耗 >= 0: 思路: 树上分组背包DP,设dp[u][k] 表示 ...
- 洛谷P1273 有线电视网 【树上分组背包】
题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从转播站到转播站以及从 ...
- 洛谷P1273 有线电视网【树形dp】
题目:https://www.luogu.org/problemnew/show/P1273 题意:一棵树,叶子节点是用户,每天边有一个权值表示花费,每一个用户有一个值表示他们会交的钱. 问在不亏本的 ...
- 洛谷 P1273 有线电视网(dp)
/* 想了半天没想出状态 自己还是太弱了 QAQ 题目问的是最多供给多少户 一般想法是把这个值定义为状态量 没想出来QAQ....看了看题解的状态 很机智.... f[i][j]表示i的子树 选了j个 ...
随机推荐
- 【下一代核心技术DevOps】:(六)Rancher集中存储及相关应用
1. 前言 为什么要使用集中存储? 使用集中存储有个很大的优势是数据安全和统一管理,和集群完美配合. 产品集成存储经历过几个阶段: 1.单机本机存储. 系统使用本地硬盘存储 2.单网络集中存储. 局域 ...
- .NETCore_初探
1. Core默认的服务注册 Statup文件(rogram类型中创建 WebHost时使用的)中有俩个方法: Configure和ConfigureServices(将服务放置到容器里面) publ ...
- 记录:EM 算法估计混合高斯模型参数
当概率模型依赖于无法观测的隐性变量时,使用普通的极大似然估计法无法估计出概率模型中参数.此时需要利用优化的极大似然估计:EM算法. 在这里我只是想要使用这个EM算法估计混合高斯模型中的参数.由于直观原 ...
- javascript DOM操作中的insertAdjacentHTML方法
插入HTML内容与文本内容以前用的是innerHTML与innerText方法,今天看到insertAdjacentHTML和 insertAdjacentText两个API,特地学习一下: inse ...
- 数组与字符串三(Cocos2d-x 3.x _Array容器)
"程序=数据结构+算法" 在面向对象的语言中,诸如数组.堆栈.队列等的结构都被封装成了特定的类,按照特定数据结构的算法设计起来,这就是容器类. Cocos2d-x中,能使用的容器类 ...
- C 实现选择排序
一.选择排序的思想 假设有一个7元素的数组 [11, 24, 5, 17, 2, 8, 20],我们通过选择排序来从小到大排序. 思想是进行7次外循环从0-->6,每一次又是一个内循环,从i+1 ...
- memcache 分布式缓存
转载地址:http://www.cnblogs.com/phpstudy2015-6/p/6713164.html 作者:那一叶随风 1.memcached分布式简介 memcached虽然称为“分布 ...
- 软件工程_4th weeks
本周要进行阿尔法版本的发布,因此我们做了一些代码和测试方面的工作.当然了下了课后第一件事还是巩固课上讲的知识,比如MVP.四象限.看了演讲<最后一课>等. 一.结对编程 本周的结对编程继续 ...
- Java微信二次开发(四)
自定义文字菜单,暂时先实现一个根据用户输入城市名称来查询邮政编码和查询区号的功能 需要导入库:mysql-connector-java-5.0.8-bin.jar 第一步:利用Navicat新建一个用 ...
- /include/caffe/common.cuh(9): error: function "atomicAdd(double *, double)" has already been defined
https://stackoverflow.com/questions/39274472/error-function-atomicadddouble-double-has-already-been- ...