倍增\ tarjan求lca
对于每个节点v,记录anc[v][k],表示从它向上走2k步后到达的节点(如果越过了根节点,那么anc[v][k]就是根节点)。
dfs函数对树进行的dfs,先求出anc[v][0],再利用anc[v][k] = anc[anc[v][k - 1]][k - 1] (从v向上2k步即为从v向上2(k - 1)步再向上2(k - 1)步)
求出其他anc[v][k]的值
lca(u, v)函数寻找u和v的lca, 首先把u和v调整到一个高度。如果此时u和v重合,那么这就是我们要找的lca,如果他们补充和,就不断的寻找一个最小的k,使得
anc[u][k] = anc[v][k]
int anc[maxn][20], deep[maxn]; int dfs(int u, int fa) { for(int i = 1; i < 20; i++) anc[u][i] = anc[anc[u][i - 1]][i - 1]; for(int i = head2[u]; i != -1; i = Edge[i].next) { int v = Edge[i].v; if(v == fa || deep[v]) continue; anc[v][0] = u; deep[v] = deep[u] + 1; dfs(v, u); } } int lca(int u, int v) { if(deep[u] < deep[v]) swap(u, v); for(int i = 20 - 1; i >= 0; i--) if(deep[anc[u][i]] >= deep[v]) u = anc[u][i]; for(int i = 20 - 1; i >= 0; i--) { if(anc[u][i] != anc[v][i]) { u = anc[u][i]; v = anc[v][i]; } } if(u == v) return u; return anc[u][0]; }
tarjan求lca
1.任选一个点为根节点,从根节点开始。
2.遍历该点u所有子节点v,并标记这些子节点v已被访问过。
3.若是v还有子节点,返回2,否则下一步。
4.合并v到u上。
5.寻找与当前点u有询问关系的点v。
合并就用并查集就好了
板子先欠着
6.若是v已经被访问过了,则可以确认u和v的最近公共祖先为v被合并到的父亲节点a。
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
分类:
学习记录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)