树形dp学习
学习博客:https://www.cnblogs.com/qq936584671/p/10274268.html
树的性质:n个点,n-1条边,任意两个点之间只存在一条路径,可以人为设置根节点,对于任意一个节点只存在至多一个父节点,其余为子节点。
记忆化树形dp模型较为抽象难以理解,以下通过由浅到深的方式解析树形dp以及树的性质。
树形dp求树的直径:(在一颗树里找到点X,Y,使得|XY|最大)

如图,我们令A为根节点,令dfs遍历顺序为ABDGHEFC。
在我们的dfs计算过程中,我们从下往上求解每一个节点,总的来说我们要求两个东西:
1、以每一个节点为根,所能到达的最长路径dp【u】
2、以每一个节点为根,它下面的的树的最长路径ans(其实就是找到 两个没有重复路径的子树,例如以B为根节点,会找到BDG+BE而不会找到BDG+BDH)
然后将子树中以子树根为起点所能到达的最长路径传给父节点,最后得出答案
具体看下面代码:
struct Node
{
int nex,val;
};
vector<Node>node[maxn];//node[u][i].nex代表该节点的子节点 node[u][i].val代表该节点与子节点之间路径的权值
void dfs(int u,int fa)//该节点和该节点的父亲
{
for(int i=;i<node[u].size();i++)
{
int v=node[u][i].nex;
if(v!=fa)//防止回到父节点
{
dfs(v,u);//
ans=max(ans,d[u]+d[v]+node[u][i].val);//这个必须在下面一步的前面
d[u]=max(d[u],d[v]+node[u][i].val);
}
}
}
理解了基本的树形dp之后,开始下面的练习:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4616
学习链接:https://www.cnblogs.com/zyb993963526/p/7223861.html
题目大意:在一颗有n(n<5e4)个节点的树中,每个节点有权值和是否有陷阱,你可以最多踏进c(c<=3)个陷阱,当你进入第c个陷阱时,你就无法继续移动了,你可以在任意节点出发,获取经过节点的权值(无法重复获取同一个节点),求能得到的最大权值和。
思路:
有点像树链剖分,对于一个以u为根的子树,因为每个顶点只能经过一次,那我们只能选择它的一个子树往下走。就像是把这棵树分成许多链,最后再连接起来。
这道题目麻烦的地方是陷阱的处理,用d【u】【j】【0/1】表示以u为根的某一子节点经过j个陷阱后到达u的最大权值和,0/1表示起点是否有陷阱。
假设当前到达u时经过了k个陷阱,分下面几种情况进行讨论:
①如果k==c,那么起点和终点至少有一个是陷阱(可能有些人会认为终点一定会是陷阱,这样是没错的,因为起点和终点时相对的,你也可以把起点看做终点)。
②如果k<c,那么起点和终点是否是陷阱是任意的,可以有也可以没有。
具体看代码:
#include<iostream>
#include<vector>
#include<math.h>
#include<string.h>
using namespace std;
const int maxn=+;
int n,c;
int ans;
vector<int>G[maxn];
int val[maxn],trap[maxn];//分别存储节点的值和是否有陷阱
int d[maxn][][];//d[u][j][0/1]表示以u为根的某一子节点经过j个陷阱之后到达u的最大权值和
void dfs(int u,int fa)
{
d[u][trap[u]][trap[u]]=val[u]; //计算以u为根的子树所能获得的最大值,也就是将子树的链进行连接
for(int i=;i<G[u].size();i++)
{
int v=G[u][i];
if(v!=fa)
{
dfs(v,u);
for(int j=;j<=c;j++)
{
for(int k=;j+k<=c;k++)
{
if(j!=c) ans=max(ans,d[u][j][]+d[v][k][]);
if(k!=c) ans=max(ans,d[u][j][]+d[v][k][]);
if(j+k<c) ans=max(ans,d[u][j][]+d[v][k][]);//起点和终点都可以为非陷阱
if(j+k<=c) ans=max(ans,d[u][j][]+d[v][k][]);//起点和终点都可以为陷阱 }
}
for(int j=;j+trap[u]<=c;j++)
{
d[u][j+trap[u]][]=max(d[u][j+trap[u]][],d[v][j][]+val[u]);
if(j!=)
{
d[u][j+trap[u]][]=max(d[u][j+trap[u]][],d[v][j][]+val[u]);
}
}
}
}
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>c;//n个节点 最多可以踩c个陷阱
for(int i=;i<n;i++) G[i].clear();
for(int i=;i<n;i++) cin>>val[i]>>trap[i];//输入值和是否有陷阱
for(int i=;i<n;i++)
{
int u,v;
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
ans=;
memset(d,,sizeof(d));
dfs(,-);
cout<<ans<<endl;
}
}
树形dp学习的更多相关文章
- 树形DP 学习笔记
树形DP学习笔记 ps: 本文内容与蓝书一致 树的重心 概念: 一颗树中的一个节点其最大子树的节点树最小 解法:对与每个节点求他儿子的\(size\) ,上方子树的节点个数为\(n-size_u\) ...
- 树形$dp$学习笔记
今天学习了树形\(dp\),一开始浏览各大\(blog\),发现都\(TM\)是题,连个入门的\(blog\)都没有,体验极差.所以我立志要写一篇可以让初学树形\(dp\)的童鞋快速入门. 树形\(d ...
- 树形DP学习笔记
树形DP 入门模板题 poj P2342 大意就是一群职员之间有上下级关系,每个职员有一个快乐值,但是只有在他的直接上级不在场的情况下才会快乐.求举行一场聚会的快乐值之和的最大值. 求解 声明一个数组 ...
- 树形DP 学习笔记(树形DP、树的直径、树的重心)
前言:寒假讲过树形DP,这次再复习一下. -------------- 基本的树形DP 实现形式 树形DP的主要实现形式是$dfs$.这是因为树的特殊结构决定的——只有确定了儿子,才能决定父亲.划分阶 ...
- 树形dp|无根树转有根树|2015年蓝桥杯生命之树
2015年蓝桥杯第十题--生命之树(无根树dfs) ①暴力解法:枚举子集(选点) + dfs判断连通性(题目要求连通)满足上面两个条件下找出最大值权值和 ②dfs无根树转有根树,递归找最优 先学习无根 ...
- 树形DP入门学习
这里是学习韦神的6道入门树形dp进行入门,本来应放在day12&&13里,但感觉这个应该单独放出来好点. 这里大部分题目都是参考的韦神的思想. A - Anniversary part ...
- [学习笔记]树形dp
最近几天学了一下树形\(dp\) 其实早就学过了 来提高一下打开树形\(dp\)的姿势. 1.没有上司的晚会 我的人生第一道树形\(dp\),其实就是两种情况: \(dp[i][1]\)表示第i个人来 ...
- bzoj2500: 幸福的道路(树形dp+单调队列)
好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...
- 【BZOJ-1060】时态同步 树形DP (DFS爆搜)
1060: [ZJOI2007]时态同步 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2101 Solved: 595[Submit][Statu ...
随机推荐
- java全栈day07---Eclipse开发工具 超市库存管理系统
前六天我们都是用Notepad++来编写java程序,通过DOS命令来运行,我们发现这样比较繁琐,那么我们今天就用一个工具Eclipse来开发java Eclipse的下载安装 * A: Eclips ...
- hustOJ SPJ(special judge)模板
#include <stdio.h> #include <math.h> #define PI acos(-1.0) #define AC 0 #define WA 1 int ...
- Java50道经典习题-程序28 排序算法
题目:对10个数进行排序分析:可以利用选择法,即从后9个比较过程中,选择一个最小的与第一个元素交换, 下次类推,即用第二个元素与后8个进行比较,并进行交换. public class Prog28 { ...
- 具有增删改查功能的表格Demo--【BootStrap】
http://blog.csdn.net/wangmei4968/article/details/48437175
- SQLServer存储引擎——03.日志
3. SQLServer存储引擎之日志篇 (3.1)日志结构 (3.1.1)物理日志 (0)物理日志即数据库的.ldf文件, 当然后缀名是可以自定义的,默认是.ldf (1)一个SqlServer数据 ...
- MySQL的ODBC安装错误问题!
MySQL的ODBC安装时候可能会出错,主要原因是缺少VC支持库,需要2010版本的VC支持库!!X86和X64分别对应MySQL对应的ODBC,不能安装一个两个都搞定,如果需要安装两个ODBC驱动, ...
- EF core 学习 执行原生sql语句 之ExecuteReader 和ExecuteScalar
通过ef core 源码分析 Microsoft.EntityFrameworkCore.Storage.RelationalCommandExtensions类中有相应的方法 为此得到相应的结果: ...
- Runtime常用的几个应用场景
Runtime常见的几个应用场景. Runtime常见应用场景 具体应用拦截系统自带的方法调用(Method Swizzling黑魔法) 实现给分类增加属性 实现字典的模型和自动转换 JSPatch替 ...
- zookeeper客户端使用第三方(Curator)封装的Api操作节点
1.为什么使用Curator? Curator本身是Netflix公司开源的zookeeper客户端: Curator 提供了各种应用场景的实现封装: curator-framework 提供了f ...
- linux 环境下tomcat中部署jfinal项目
tomcat中部署jfinal项目 问题现象如下图 问题描述: 我在自己的windows7系统上tomcat下面跑这个项目没有任何问题吗,但是当我把项目上传到linux服务器上的tomcatwebap ...