学习博客: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学习的更多相关文章

  1. 树形DP 学习笔记

    树形DP学习笔记 ps: 本文内容与蓝书一致 树的重心 概念: 一颗树中的一个节点其最大子树的节点树最小 解法:对与每个节点求他儿子的\(size\) ,上方子树的节点个数为\(n-size_u\) ...

  2. 树形$dp$学习笔记

    今天学习了树形\(dp\),一开始浏览各大\(blog\),发现都\(TM\)是题,连个入门的\(blog\)都没有,体验极差.所以我立志要写一篇可以让初学树形\(dp\)的童鞋快速入门. 树形\(d ...

  3. 树形DP学习笔记

    树形DP 入门模板题 poj P2342 大意就是一群职员之间有上下级关系,每个职员有一个快乐值,但是只有在他的直接上级不在场的情况下才会快乐.求举行一场聚会的快乐值之和的最大值. 求解 声明一个数组 ...

  4. 树形DP 学习笔记(树形DP、树的直径、树的重心)

    前言:寒假讲过树形DP,这次再复习一下. -------------- 基本的树形DP 实现形式 树形DP的主要实现形式是$dfs$.这是因为树的特殊结构决定的——只有确定了儿子,才能决定父亲.划分阶 ...

  5. 树形dp|无根树转有根树|2015年蓝桥杯生命之树

    2015年蓝桥杯第十题--生命之树(无根树dfs) ①暴力解法:枚举子集(选点) + dfs判断连通性(题目要求连通)满足上面两个条件下找出最大值权值和 ②dfs无根树转有根树,递归找最优 先学习无根 ...

  6. 树形DP入门学习

    这里是学习韦神的6道入门树形dp进行入门,本来应放在day12&&13里,但感觉这个应该单独放出来好点. 这里大部分题目都是参考的韦神的思想. A - Anniversary part ...

  7. [学习笔记]树形dp

    最近几天学了一下树形\(dp\) 其实早就学过了 来提高一下打开树形\(dp\)的姿势. 1.没有上司的晚会 我的人生第一道树形\(dp\),其实就是两种情况: \(dp[i][1]\)表示第i个人来 ...

  8. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

  9. 【BZOJ-1060】时态同步 树形DP (DFS爆搜)

    1060: [ZJOI2007]时态同步 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2101  Solved: 595[Submit][Statu ...

随机推荐

  1. 福大软工1816 · 第五次作业 - 结对作业2_EXE图片_备用

    1_每日推荐界面.png 2_论文搜索界面.png 2_论文搜索界面_搜索功能.png 3_流行趋势_十大热词排名统计图.png 4_人物界面.png 5_我的收藏界面.png 6_设置界面.png ...

  2. 操作系统 Linux ex2 note

    locate filename 搜索文件 将当前用户目录下的文件清单输出到文件list1.txt(当前用户目录下)中.ls -l > list1.txt 利用管道命令将根(/)下所有修改日期在4 ...

  3. WordCountPro小程序

    WordCountPro小程序 基本任务 1.githu地址 https://github.com/JarrySmith/WordCountPro 2.psp2.1表   PSP2.1 PSP阶段 预 ...

  4. win10开机时不显示锁屏壁纸

    win10开机壁纸存放在此目录下: C:\Users\%username%\AppData\Local\Packages\Microsoft.Windows.ContentDeliveryManage ...

  5. Ubuntu中安装LAMP

    现在,很多人可能已经用上ubuntu了,大家可能花了大量时间在ubuntu的美化上,这无可厚非,但是,ubuntu应该给我们的工作和学习带来更多的便利和方便.ubuntu作为linux,为我们提供了强 ...

  6. C# Socket 接受数据不全的处理

    由于Socket 一次传输数据有限,因此需要多次接受数据传输. 解决办法一:     int numberOfBytesRead = 0;     int totalNumberOfBytes = 0 ...

  7. SQL server 提取字符中第一次和最后一次出现的数字

    CREATE FUNCTION [dbo].[StringExtractNumber(FirstOrLast)](@address nvarchar(max),@firstOrLast INT) re ...

  8. Spring Boot 学习系列(02)—使用热部署,提升开发效

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 开发调试很简单 热部署的使用非常简单,但能极大的提高我们的开发效率,像传统的web应用,我们修改后需要重新编 ...

  9. 659. Split Array into Consecutive Subsequences

    You are given an integer array sorted in ascending order (may contain duplicates), you need to split ...

  10. React-Native App启动页制作(安卓端)

    原文地址:React-Native App启动页制作(安卓端) 这篇文章是根据开源项目react-native-splash-screen来写的.在使用react-native-link命令安装该包后 ...