树行DP小结
顾名思义:就是在树上做的DP,依据DFS的性质,在访问过儿子之后返回后将儿子的状态传递给父亲...
先看例题:

此题用贪心也能过,不过正解是DP。
对于树上的DP我们可以直接考虑最优解下各点的状态来方便我们设状态.显然信号联通的树上各点只有三中状态,自己有塔,儿子有塔,父亲有塔.
那我们设状态时就可以用f[x][0],f[x][1],f[x][2]表示儿子有塔,自己有塔,父亲有塔...
对于1和2的状态比较好转移:
f[x][1]+=min(f[y][1],min(f[y][0],f[y][2]));
f[x][2]+=min(f[y][1],f[y][0]);
那对于0的状态,则可以枚举哪个儿子有塔,用计算好的f[x][2]的值:
f[x][0]=min(f[x][0],f[x][2]-min(f[y][1],f[y][0])+f[y][1]); (好好考虑)
初始化,f[x][1]=1;f[x][0]=INT_MAX;
代码:
#include<bits/stdc++.h>
#define _ 0
using namespace std;
const int maxn=10010;
int n,tot,link[maxn],f[maxn][4],fa[maxn]; //f[i][1]表示自己用。
struct bian //f[i][0]表示儿子用.f[i][2]表示父亲用.
{
int y,next;
};
bian a[2*maxn];
inline void add(int x,int y)
{
a[++tot].y=y;
a[tot].next=link[x];
link[x]=tot;
}
inline void dfs(int x)
{
f[x][1]=1;f[x][0]=INT_MAX;
for(int i=link[x];i;i=a[i].next)
{
int y=a[i].y;
if(y==fa[x]) continue;
fa[y]=x;
dfs(y);
f[x][1]+=min(f[y][1],min(f[y][0],f[y][2]));
f[x][2]+=min(f[y][1],f[y][0]);
}
for(int i=link[x];i;i=a[i].next)
{
int y=a[i].y;
if(y==fa[x]) continue;
f[x][0]=min(f[x][0],f[x][2]-min(f[y][1],f[y][0])+f[y][1]);
}
}
int main()
{
//freopen("1.in","r",stdin);
cin>>n;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
add(x,y);add(y,x);
}
dfs(1);
cout<<min(f[1][1],f[1][0]);
return (0^_^0);
}
下一题:

这道题同样是树上跑DP.
状态很好想,f[x][j]表示x的节点保留j条树枝的最大值.
#include<bits/stdc++.h>
#define _ 0
using namespace std;
const int maxn=110;
int n,Q,tot,link[maxn],f[maxn][maxn],size[maxn],fa[maxn],deep[maxn];
struct bian //f[i][j]表示i点保留了j条边的最大苹果数.
{
int y,v,next;
};
bian a[2*maxn];
inline void add(int x,int y,int v)
{
a[++tot].y=y;
a[tot].v=v;
a[tot].next=link[x];
link[x]=tot;
}
inline void dfs(int x)
{
size[x]=1;
for(int i=link[x];i;i=a[i].next)
{
int y=a[i].y;
if(deep[y]) continue;
deep[y]=deep[x]+1; //计算它的深度.
dfs(y);
size[x]+=size[y]; //计算以其为根节点的子树数量
for(int j=min(Q-deep[x]+1,size[x]-1);j>=0;--j) //见下
for(int k=min(Q-deep[y]+1,min(size[y]-1,j-1));k>=0;--k) //见下
f[x][j]=max(f[x][j],f[x][j-k-1]+f[y][k]+a[i].v);
}
}
int main()
{
freopen("1.in","r",stdin);
cin>>n>>Q;
for(int i=1;i<=n;i++)
{
int x,y,v;
cin>>x>>y>>v;
add(x,y,v);add(y,x,v);
}
deep[1]=1; //对深度初始化.
dfs(1);
cout<<f[1][Q]<<endl;
return (0^_^0);
}
这里主要讲j和k的范围,想说j,Q-deep[x]+1表示要想选到x这个点必须保留deep[x]+1个树枝.size[x]-1表示x此时最多选的树枝.
同理,k还多了个j-1,因为还要选x到y这条边,所以要建议.
这里警告我:状态转移必须在合理的范围内,否则会出现不可预计的后果.还有f循环的顺序考虑清楚.
例如此题j就必须是倒序的。因为是拿y来更新x的,比如假如正序:拿f[y][1]更新过f[x][2]后,又拿f[X][2]更新f[x][3]这就不符合情况.此时倒序,由大的枚举就不会出现这种情况了。
好了,就到这了.
树行DP小结的更多相关文章
- 【BZOJ-3572】世界树 虚树 + 树形DP
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1084 Solved: 611[Submit][Status ...
- 【BZOJ-2286】消耗战 虚树 + 树形DP
2286: [Sdoi2011消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2120 Solved: 752[Submit][Status] ...
- 【XSY1905】【XSY2761】新访问计划 二分 树型DP
题目描述 给你一棵树,你要从\(1\)号点出发,经过这棵树的每条边至少一次,最后回到\(1\)号点,经过一条边要花费\(w_i\)的时间. 你还可以乘车,从一个点取另一个点,需要花费\(c\)的时间. ...
- [Codeforces743D][luogu CF743D]Chloe and pleasant prizes[树状DP入门][毒瘤数据]
这个题的数据真的很毒瘤,身为一个交了8遍的蒟蒻的呐喊(嘤嘤嘤) 个人认为作为一个树状DP的入门题十分合适,同时建议做完这个题之后再去做一下这个题 选课 同时在这里挂一个选取节点型树形DP的状态转移方程 ...
- 2018.09.12 poj2376Cleaning Shifts(线段树+简单dp)
传送门 貌似贪心能过啊%%%. 本蒟蒻写的线段树优化dp. 式子很好推啊. f[i]表示覆盖1~i所需的最小代价. 那么显然对于一个区间[li,ri]" role="present ...
- BZOJ2090: [Poi2010]Monotonicity 2【线段树优化DP】
BZOJ2090: [Poi2010]Monotonicity 2[线段树优化DP] Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. ...
- bzoj 2286(虚树+树形dp) 虚树模板
树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5002 Sol ...
- 洛谷 P1453 城市环路 ( 基环树树形dp )
题目链接 题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域--城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市 ...
- BZOJ 1564 :[NOI2009]二叉查找树(树型DP)
二叉查找树 [题目描述] 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子结点的数据值小. 另一方面,这棵查找树中每个结点都有一个权值,每个结 ...
随机推荐
- POJ1861 Network (Kruskal算法 +并查集)
Network Description Andrew is working as system administrator and is planning to establish a new net ...
- 解析Markdown文件生成React组件文档
前言 最近做的项目使用了微前端框架single-spa. 对于这类微前端框架而言,通常有个utility应用,也就是公共应用,里面是各个子应用之间可以共用的一些公共组件或者方法. 对于一个团队而言,项 ...
- 学习PHP中的国际化功能来查看货币及日期信息
做为一门在世界范围内广泛使用的编程语言,国际化能力往往是衡量一个编程语言是否能够大范围流行的重要内容.特别是对于 PHP 这种以 Web 页面编程为主战场的语言来说,国际化能力更是重中之重.在 PHP ...
- Git报错-refusing to merge unrelated histories
执行git pull 时报错: 出现这个问题的最主要原因还是在于本地仓库和远程仓库实际上是独立的两个仓库.假如我之前是直接clone的方式在本地建立起远程github仓库的克隆本地仓库就不会有这问题了 ...
- 低差异序列 (low-discrepancy sequences)之Halton序列均匀产生多维随机数的介绍与实现
Halton序列 在统计学中,Halton序列是用于生成空间中的点的序列,如Monte Carlo模拟的数值方法,虽然这些序列是确定性的,但它们的差异性很低,也就是说,在许多方面看起来是随机的.它们在 ...
- P3760-[TJOI2017]异或和【树状数组】
正题 题目链接:https://www.luogu.com.cn/problem/P3760 题目大意 给出\(n\)个数字的一个序列\(a\),求它所有区间和的异或和 \(n\leq 10^5,\s ...
- windows使用VS编译python源码
使用VS2021编译python源码 说明,使用VS2019也是可以的. 环境准备 对于VS2019首要要安装必要的环境 到python官网下载源码压缩包以及解压(红色箭头任选一个都行) 打开下载好的 ...
- Android12系统源码分析:NativeTombstoneManager
Android12系统源码分析:NativeTombstoneManager 概述 android12新增的system_server进程(LocalService)本地服务,用于管理native t ...
- Java实现红黑树(平衡二叉树)
前言 在实现红黑树之前,我们先来了解一下符号表. 符号表的描述借鉴了Algorithms第四版,详情在:https://algs4.cs.princeton.edu/home/ 符号表有时候被称为字典 ...
- 前段之BOM ----DOM
一.介绍 BOM(Browser Object Model)是指浏览器对象模型,它使 JavaScript 有能力与浏览器进行"对话". DOM (Document Object ...