顾名思义:就是在树上做的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小结的更多相关文章

  1. 【BZOJ-3572】世界树 虚树 + 树形DP

    3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1084  Solved: 611[Submit][Status ...

  2. 【BZOJ-2286】消耗战 虚树 + 树形DP

    2286: [Sdoi2011消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2120  Solved: 752[Submit][Status] ...

  3. 【XSY1905】【XSY2761】新访问计划 二分 树型DP

    题目描述 给你一棵树,你要从\(1\)号点出发,经过这棵树的每条边至少一次,最后回到\(1\)号点,经过一条边要花费\(w_i\)的时间. 你还可以乘车,从一个点取另一个点,需要花费\(c\)的时间. ...

  4. [Codeforces743D][luogu CF743D]Chloe and pleasant prizes[树状DP入门][毒瘤数据]

    这个题的数据真的很毒瘤,身为一个交了8遍的蒟蒻的呐喊(嘤嘤嘤) 个人认为作为一个树状DP的入门题十分合适,同时建议做完这个题之后再去做一下这个题 选课 同时在这里挂一个选取节点型树形DP的状态转移方程 ...

  5. 2018.09.12 poj2376Cleaning Shifts(线段树+简单dp)

    传送门 貌似贪心能过啊%%%. 本蒟蒻写的线段树优化dp. 式子很好推啊. f[i]表示覆盖1~i所需的最小代价. 那么显然对于一个区间[li,ri]" role="present ...

  6. BZOJ2090: [Poi2010]Monotonicity 2【线段树优化DP】

    BZOJ2090: [Poi2010]Monotonicity 2[线段树优化DP] Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. ...

  7. bzoj 2286(虚树+树形dp) 虚树模板

    树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5002  Sol ...

  8. 洛谷 P1453 城市环路 ( 基环树树形dp )

    题目链接 题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域--城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市 ...

  9. BZOJ 1564 :[NOI2009]二叉查找树(树型DP)

    二叉查找树 [题目描述] 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子结点的数据值小. 另一方面,这棵查找树中每个结点都有一个权值,每个结 ...

随机推荐

  1. 215 day01_Object类、常用API

    day01[Object类.常用API] 主要内容 Object类 Date类 DateFormat类 Calendar类 System类 StringBuilder类 包装类 教学目标 -[ ] 能 ...

  2. ARP-NAT(MAC Address Translation)的原理

    本文部分图片来自: http://wiki.deliberant.com/faq/wireless-bridge-routing-arpnat/ https://wiki.openwrt.org/do ...

  3. PHP设计模式之访问者模式

    访问者,就像我们去别人家访问,或者别人来我们家看望我们一样.我们每个人都像是一个实体,而来访的人都会一一的和我们打招呼.毕竟,我们中华民族是非常讲究礼数和好客的民族.访问者是GoF23个设计模式中最复 ...

  4. webpack4 使用babel处理ES6语法的一些简单配置

    一,安装包 npm install --save-dev babel-loader @babel/corenpm install @babel/preset-env --save-devnpm ins ...

  5. rabbitmqctl 命令行管理工具

    1. 用户管理 用户管理包括增加用户,删除用户,查看用户列表,修改用户密码. (1) 新增一个用户 rabbitmqctl add_user Username Password (2) 删除一个用户 ...

  6. Orchar Core 创建一个模块化的ASP.NET Core应用程序

    您将构建什么?您将构建一个模块化的ASP.NET Core MVC Web应用程序,类似于Orchard Core附带的示例"Hello World"应用程序.它包括一个Web应用 ...

  7. JDK1.8源码(四)——java.util.Arrays类

    一.概述 1.介绍 Arrays 类是 JDK1.2 提供的一个工具类,提供处理数组的各种方法,基本上都是静态方法,能直接通过类名Arrays调用. 二.类源码 1.asList()方法 将一个泛型数 ...

  8. Kotlin协程基础

    开发环境 IntelliJ IDEA 2021.2.2 (Community Edition) Kotlin: 212-1.5.10-release-IJ5284.40 我们已经通过第一个例子学会了启 ...

  9. 如何使用jemeter进行性能测试

    下载链接:http://jmeter.apache.org/download_jmeter.cgi 一:如何使用jemeter进行压测 1)稳定性测试就需要长时间运行,其运行时间1天.2天.一周等 2 ...

  10. django 自定义auth中user登陆认证以及自写认证

    第一种: 重写自定义auth中user登陆认证模块, 引入MobelBackend from django.contrib.auth.backends import ModelBackend 重写验证 ...