当前位置: 首页 > news >正文

树上dp学习总结2

今天也是侥幸刷了两道树上dp的问题,第一个还算简单,但是第二个真的可以说是我碰到的蓝题之首,做了一个晚上我只能留下了不争气的口水(太饿了,该吃夜宵了)

P1131 [ZJOI2007] 时态同步

 

 思路:一开始我想的是深搜一遍,然后求出每个节点到根节点的距离,然后找到最大值,然后求出所有的叶子结点和根结点的差值即可

但是这是不对的,因为如果这样会重复计算一些公共边,导致最后的结果产生错误 ,因此我们只需要每次将处理的叶子结点能够持平就可以了

如图所示

因此我们就可以写出代码

 

#include<bits/stdc++.h>
using namespace std;  
#define int long long 
vector<pair<int, int>> edges[500005]; 
int n, rt; 
long long f[500005], ans; void dfs(int v, int parent) 
{int len = edges[v].size();  for (int i = 0; i < len; i++) {  int u = edges[v][i].first; int weight = edges[v][i].second; if (u == parent) continue; dfs(u, v); f[v]=max(f[v], f[u] + weight); //计算最大权重 }  for (int i = 0; i < len; i++) {  int u = edges[v][i].first; int weight = edges[v][i].second; if (u == parent) continue; ans += (f[v]-f[u]-weight); }  
}  
signed main() 
{  cin >> n >> rt;  for (int i = 1; i < n; i++) {  int a, b, c;  cin >> a >> b >> c; edges[a].emplace_back(b, c); edges[b].emplace_back(a, c); }  dfs(rt,-1); cout<<ans; return 0;  
}

P2279 [HNOI2003] 消防局的设立

思路:这题是我真没想到的,巨难的题目,五个状态转移方程,看了大犇的代码才会写,只能说我还是个小蒟蒻

先来说一下状态转移数组的含义:

f[i][0]表示可以覆盖到从节点i向上2层的最小消防站个数
f[i][1]表示可以覆盖到从节点i向上1层的最小消防站个数
f[i][2]表示可以覆盖到从节点i向上0层的最小消防站个数
f[i][3]表示可以覆盖到从节点i向上-1层的最小消防站个数
f[i][4]表示可以覆盖到从节点i向上-2层的最小消防站个数 

什么叫做覆盖呢?就是说,确保消防站的覆盖范围可以覆盖到其层数以及其子树

比如说,f[ v ] [ 1]就是说要覆盖其父亲节点以及包括其自身的所有子树

f[ v ] [3] 就是要包含其儿子以及所有子孙的子树

因此我们可以找到状态转移方程

这里直接引用大犇说的话了,引用链接:大犇的题解文章 

 

因此我们就可以写出dfs函数,完成这道题了

#include<bits/stdc++.h>  
using namespace std;  
#define int long long   
int n;  
vector<int> G[1005]; 
int f[1005][5]; 
void dfs(int v) 
{  f[v][0] = 1;  f[v][3] = 0;  f[v][4] = 0;  for (int u:G[v]) {  dfs(u);  f[v][0]+=f[u][4];  f[v][3]+=f[u][2];  f[v][4]+=f[u][3];  }  if (G[v].empty()) {  f[v][1]=f[v][2]=1; } else {  f[v][1]=f[v][2]=0x3f3f3f3f;  for(int i = 0;i<G[v].size();i++) {  int u=G[v][i]; int f1=f[u][0];  int f2=f[u][1];  for (int j=0;j<G[v].size();j++) {  if (i == j) continue;   int t=G[v][j]; //除了u外的别的子树 f1+=f[t][3];  f2+=f[t][2];  }  f[v][1]=min(f[v][1],f1);  f[v][2]=min(f[v][2],f2);  }  }  for(int i=1;i<=4;i++) {  f[v][i]=min(f[v][i],f[v][i-1]);  }  
}  
signed main() 
{  cin>>n;  memset(f,0x3f3f3f3f,sizeof(f));for (int i=2;i<=n;i++) {  int v;  cin>>v;  G[v].push_back(i);   }  dfs(1);  cout<<f[1][2]<<endl;  return 0;  
}

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • SpringMVC中的常用注解
  • stl-algorithm【1】
  • 【错误总结】Ubuntu系统中执行 sudo apt-get update报错
  • 随着人工智能技术的发展,如何确保其决策过程的透明度和可解释性,以避免潜在的不公正和歧视?
  • 入门 PyQt6 看过来(案例)18~ 表格属性
  • 【MATLAB源码】机器视觉与图像识别技术实战示例文档---鱼苗面积预测计数
  • 机器学习模型选择与优化: 打造智能IDS
  • 程序员面试中的“八股文”:敲门砖还是绊脚石?
  • M12电连接器的编码分类及应用领域分析
  • 在Linux上编译软件并且运行的入门示例
  • 同城校园跑腿外卖配送平台源码,这套目前全网还没有人分享过
  • 技术学习笔记2:std::bad_cast 在多态编程中有什么作用,如何避免类型转换失败?
  • 面向未来的S2B2C电商供应链系统发展趋势与创新探索
  • 从零入门 AI for Science(AI+药物) #Datawhale AI 夏令营 Task2
  • 使用mysql 的全文检索
  • python3.6+scrapy+mysql 爬虫实战
  • $translatePartialLoader加载失败及解决方式
  • 345-反转字符串中的元音字母
  • canvas绘制圆角头像
  • Elasticsearch 参考指南(升级前重新索引)
  • Flex布局到底解决了什么问题
  • Node + FFmpeg 实现Canvas动画导出视频
  • React Native移动开发实战-3-实现页面间的数据传递
  • Spring Cloud中负载均衡器概览
  • SpriteKit 技巧之添加背景图片
  • Swift 中的尾递归和蹦床
  • windows-nginx-https-本地配置
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 安卓应用性能调试和优化经验分享
  • 初识MongoDB分片
  • 构造函数(constructor)与原型链(prototype)关系
  • 如何编写一个可升级的智能合约
  • 如何利用MongoDB打造TOP榜小程序
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • ​【经验分享】微机原理、指令判断、判断指令是否正确判断指令是否正确​
  • ​TypeScript都不会用,也敢说会前端?
  • ​卜东波研究员:高观点下的少儿计算思维
  • ​补​充​经​纬​恒​润​一​面​
  • #ifdef 的技巧用法
  • #stm32整理(一)flash读写
  • (2024最新)CentOS 7上在线安装MySQL 5.7|喂饭级教程
  • (安卓)跳转应用市场APP详情页的方式
  • (二开)Flink 修改源码拓展 SQL 语法
  • (二十六)Java 数据结构
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (回溯) LeetCode 78. 子集
  • (一)Thymeleaf用法——Thymeleaf简介
  • (一)WLAN定义和基本架构转
  • (转)Mysql的优化设置
  • (转)Windows2003安全设置/维护
  • ..回顾17,展望18
  • .NET 依赖注入和配置系统
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .net打印*三角形