算法学习记录:有关树的基础
前言:
算法学习记录不是算法介绍,本文记录的是从零开始的学习过程(见到的例题,代码的理解……),所有内容按学习顺序更新,而且不保证正确,如有错误,请帮助指出。
学习工具:蓝桥OJ,LeetCode
本文归纳到目前为止见到的树。只需关注各个题目中有关树的部分即可。
目录
前言:
正文:
例题集:
1.蓝桥OJ 8617:LCA树上倍增
2.模型题:树型DP
正文:
对于一般的树:
数据量小时,用二维数组存储。
数据量大时,链式前向星(数组模拟链表)
重点记录一下链式前向星这种方法:
建立树:
#include <bits/stdc++.h>
using namespace std;
#define maxn 110000
int n, val[maxn];
struct Edge
{int nex, to;
}edge[maxn << 1];
int head[maxn], cnt;
int f[maxn][2];
void add(int from, int to)
{edge[++cnt].nex = head[from];//当前这条从from出发的边上一条边的编号head[from] = cnt; //从from出发的最新的一条边的编号edge[cnt].to = to; //当前边是到to去的return ;
}int main()
{for (int i = 1; i < n; ++ i ){int u, v;scanf("%d%d", &u, &v);add(u, v), add(v, u); //双向边}return 0;
}
结构体edge用来存边:
里边的元素:nex和to
分别表示:同节点下上一条边的编号、这条边指向的结点编号。
head数组可以理解为构建链表时用的头节点,帮助构建链表并作为该链表的入口
遍历树:
void dfs(int u, int fa)
{for (int i = head[u]; i; i = edge[i].nex){int v = edge[i].to;if (v == fa)continue;dfs(v, u);f[u][0] += max(f[v][0], f[v][1]);f[u][1] += f[v][0];}return ;
}//dfs(1,0);
i始终表示编号,第一次进入循环,i被赋值为该节点所连出的最后一条边的编号
v被赋值为这条边指向的结点编号
(因为是双向边)判断是否下一个结点是父节点,是的话跳过本次循环
下一次循环时,i被赋值edge[i].nex即这条边的上一条边的编号,
直到该编号为0,i=0循环结束
总结一下:
这种方法类似链表,每个结点、每条边都有编号,
类似链表的这种结构建立在每个结点下:
即该结点的每条边按照从后往前的顺序被连接形成“单链表”
这样做是为了遍历,并且能够存较大数据。
例题集:
1.蓝桥OJ 8617:LCA树上倍增
#include <bits/stdc++.h>using LL = long long;
using Pair = std::pair<int, int>;
#define inf 1'000'000'000'void solve(const int &Case) {int n;std::cin >> n;std::vector<std::vector<int>> G(n + 1);for (int i = 1; i < n; i++) {int u, v;std::cin >> u >> v;G[u].push_back(v), G[v].push_back(u);}std::vector<std::array<int, 21>> F(n + 1);std::vector<int> dep(n + 1);std::function<void(int, int)> dfs = [&](int x, int fax) {F[x][0] = fax;for (int i = 1; i <= 20; i++)F[x][i] = F[F[x][i - 1]][i - 1];for (const auto &tox: G[x]) {if (tox == fax)continue;dep[tox] = dep[x] + 1;dfs(tox, x);}};dfs(1, 0);auto glca = [&](int x, int y) {if (dep[x] < dep[y])std::swap(x, y);int d = dep[x] - dep[y];for (int i = 20; i >= 0; i--)if (d >> i & 1)x = F[x][i];if (x == y)return x;for (int i = 20; i >= 0; i--) {if (F[x][i] != F[y][i]) {x = F[x][i];y = F[y][i];}}return F[x][0];};int q;std::cin >> q;while (q--) {int x, y;std::cin >> x >> y;std::cout << glca(x, y) << '\n';}
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout.tie(nullptr);int T = 1;for (int Case = 1; Case <= T; Case++)solve(Case);return 0;
}
这题中使用二维数组存储了树,遍历数组G 就是在遍历树上的每一个结点
对于每一个结点,数组里存着它的父节点和子节点对应编号。
dfs函数的两个参数分别是:子节点编号和父节点编号
dep数组用来存放深度
2.模型题:树型DP

#include <bits/stdc++.h>
using namespace std;
#define maxn 110000
int n, val[maxn];
struct Edge
{int nex, to;
}edge[maxn << 1];
int head[maxn], cnt;
int f[maxn][2];
void add(int from, int to)
{edge[++cnt].nex = head[from];//当前这条从from出发的边上一条边的编号head[from] = cnt; //从from出发的最新的一条边的编号edge[cnt].to = to; //当前边是到to去的return ;
}
void dfs(int u, int fa)
{for (int i = head[u]; i; i = edge[i].nex){int v = edge[i].to;if (v == fa)continue;dfs(v, u);f[u][0] += max(f[v][0], f[v][1]);f[u][1] += f[v][0];}return ;
}
int main()
{scanf("%d", &n);for (int i = 1; i <= n; ++ i )scanf("%d", &val[i]), f[i][1] = val[i];for (int i = 1; i < n; ++ i ){int u, v;scanf("%d%d", &u, &v);add(u, v), add(v, u);}dfs(1, 0);printf("%d\n", max(f[1][0], f[1][1]));return 0;
}
DP的题目就是在遍历树时加一个dp 数组,伴随遍历过程完成动态规划的数组更新。
相关文章:
算法学习记录:有关树的基础
前言: 算法学习记录不是算法介绍,本文记录的是从零开始的学习过程(见到的例题,代码的理解……),所有内容按学习顺序更新,而且不保证正确,如有错误,请帮助指出。 学习工具…...
2. 《大数据之路:阿里巴巴大数据实践》学习笔记,持续更新ing
笔记链接(飞书):https://t0s016els2a.feishu.cn/docx/JrNydGljUonH1ExcGCpcoC8unTb 密码:r661391 该书籍部分目录如下: 文章目录 第1篇 数据技术篇第2章 日志采集2.1 浏览器的页面日志采集2.1.1 页面浏览日志采集流程2.1.2 页面交互日志采集…...
编程笔记 html5cssjs 062 JavaScrip如何使用
编程笔记 html5&css&js 062 JavaScrip如何使用 一、 引入JavaScript二、DOM操作三、事件处理四、数据验证五、异步编程六、使用库和框架七、模块化开发小结 开始学习使用JavaScript进行前端开发的基本步骤和常见实践。 这里先列示基本的步骤和内容,后面慢慢…...
【前端基础--7】
DOM操作 DOM,全称(Document Object Model),文档对象模型。 提供操作HTML的方法(操作页面元素) 获取节点 --- 操作元素标签 <body><div id"box">我是盒子标签</div><p class"text"&g…...
微信小程序如何搜索iBeacon设备
1.首先在utils文件夹下创建bluetooth.js和ibeacon.js 2.在 bluetooth.js文件中写入 module.exports {initBluetooth: function () {// 初始化蓝牙模块wx.openBluetoothAdapter({success: function (res) {console.log(蓝牙模块初始化成功);},fail: function (res) {console.l…...
JVM篇:垃圾回收算法
标记清除 通过遍历GC Root后得到不再被引用的对象,对没被引用的对象做一个标记处理,然后对其进行清除。 优点:速度快 缺点:会产生内存碎片,可能会导致空闲的内存足够保存对象,但由于不连续而保存失败。 标…...
2024年数学建模美赛 分析与编程
2024年数学建模美赛 分析与编程 1、本专栏将在2024年美赛题目公布后,进行深入分析,建议收藏; 2、本专栏对2023年赛题,其它题目分析详见专题讨论; 2023年数学建模美赛A题(A drought stricken plant communi…...
05-Nacos-配置中心接入
1、pom依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency> 2、配置文件 spring:application:name: nacos-config## 当前环境,这个和…...
服务端开发小记02——Maven
这里写目录标题 Maven简介Maven在Linux下的安装Maven常用命令 Maven简介 Apache Maven Project是一个apache的开源项目,是用于构建和管理Java项目的工具包。 用Maven可以方便地创建项目,基于archetype可以创建多种类型的java项目;Maven仓库…...
DjangoURL调度器(一)
一、介绍 当一个用户请求 Django 站点的一个页面,下面是 Django 系统决定执行哪个 Python 代码使用的算法: Django确定要使用的根URLconf模块,一般是在settings中的ROOT_URLCONF设置的值,但是如果传入 HttpRequest 对象具有一个ur…...
Typora 无法导出 pdf 问题的解决
目录 问题描述 解决困难 解决方法 问题描述 我的 Windows 下,以前(Windows 11) Typora 可以顺利较快地由 .md 导出 .pdf 文件,此功能当然非常实用与重要。 然而,有一次电脑因故重装了系统(刷机&#x…...
uniapp封装公共的方法或者数据请求方法
仅供自己参考,不是每个页面都用到这个方法,所以我直接在用到的页面引用该公用方法: 1、新建一个util.js文件 export const address function(options){return new Promise((resolve,reject)>{uni.request({url:"https://x.cxniu.…...
SpringBoot AOP应用(公共字段填充)
背景 在很多场景下,我们对需要对一些公共字段进行赋值操作,如果我们每一个公共字段都进行代码赋值那无疑会增加很多重复无用代码,都会导致我们的 代码臃肿,所以我们使用AOP切面编程,实现功能增强,来完成公…...
NIO案例-聊天室
NIO案例-聊天室 1. 聊天室服务端编写 package com.my.io.chat.server; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.StandardCharsets; import java.util.Iterato…...
文心一言情感关怀之旅
【AGIFoundathon】文心一言情感关怀之旅,让我们一起来体验吧! 上传一张照片,用ernie-bot生成专属于你的小故事! 此项目主要使用clip_interrogator获取图片的关键信息,然后将此关键信息用百度翻译API翻译成中文后,使用封装了⼀⾔API的Ernie Bot SDK(ernie-bot)生成故事…...
mac电脑安卓文件传输工具:Android File Transfer直装版
Android File Transfer(AFT)是一款用于在Mac操作系统上与Android设备之间传输文件。它允许用户将照片、音乐、视频和其他文件从他们的Android手机或平板电脑传输到Mac电脑,以及将文件从Mac上传到Android设备。 下载地址:https://w…...
第九篇【传奇开心果系列】beeware的toga开发移动应用示例:人口普查手机应用
传奇开心果博文系列 系列博文目录beeware的toga开发移动应用示例系列博文目录一、项目目标二、安装依赖三、实现应用雏形示例代码四、扩展功能和组件的考量五、添加更多输入字段示例代码六、添加验证功能示例代码七、添加数据存储功能示例代码八、添加数据展示功能示例代码九、…...
14.5 Flash查询和添加数据库数据
14.5 Flash查询和添加数据库数据 在Flash与数据库通讯的实际应用中,如何实现用户的登录与注册是经常遇到的一个问题。登录实际上就是ASP根据Flash提供的数据查询数据库的过程,而注册则是ASP将Flash提供的数据写入数据库的过程。 1.启动Access2003&…...
[C#]winform部署yolov7+CRNN实现车牌颜色识别车牌号检测识别
【官方框架地址】 https://github.com/WongKinYiu/yolov7.git 【框架介绍】 Yolov7是一种目标检测算法,全称You Only Look Once version 7。它是继Yolov3和Yolov4之后的又一重要成果,是目标检测领域的一个重要里程碑。 Yolov7在算法结构上继承了其前…...
VBA技术资料MF111:将表对象转换为正常范围
我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。我的教程一共九套,分为初级、中级、高级三大部分。是对VBA的系统讲解,从简单的入门,到…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...
路由基础-路由表
本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中,往往存在多个不同的IP网段,数据在不同的IP网段之间交互是需要借助三层设备的,这些设备具备路由能力,能够实现数据的跨网段转发。 路由是数据通信网络中最基…...
在Zenodo下载文件 用到googlecolab googledrive
方法:Figshare/Zenodo上的数据/文件下载不下来?尝试利用Google Colab :https://zhuanlan.zhihu.com/p/1898503078782674027 参考: 通过Colab&谷歌云下载Figshare数据,超级实用!!࿰…...
