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

【笔记】最近公共祖先 - 倍增

最近公共祖先(LCA)

Luogu P3379【模板】最近公共祖先(LCA)

倍增能在 \(\log(n)\) 解决从 \(u\)\(v\) 的路线问题。

我们往上跳,\(f[i][j]\) 表示 \(i\) 节点往上跳 \(2^j\) 步。

\(f[i][0]=father[i]\)

\(f[i][1]=f[f[i][0]][0]\)

\(f[i][2]=f[f[i][1]][1]\)

\(f[i][j]=f[f[i][j-1]][j-1]\)

实现:如果两个点往上跳的点一样就不跳并减半,最后求跳完之后两个节点的父亲。

先大步再小步。

预处理:建树,求每个点深度以及倍增跳步所达到的点。

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=5e5+10;
struct Node{int to,nxt;
}e[2*maxn];
int n,m,s,D;
int tot,h[maxn],dep[maxn],fa[maxn][20];
void Add(int u,int v){tot++;e[tot].to=v;e[tot].nxt=h[u];h[u]=tot;
}
void Dfs(int root,int cur,int fath){fa[root][0]=fath;D=max(D,cur);dep[root]=cur;for(int i=1;i<=log(dep[root])/log(2);i++){fa[root][i]=fa[fa[root][i-1]][i-1];}for(int i=h[root];i!=-1;i=e[i].nxt){int v=e[i].to;if(v!=fath) Dfs(v,cur+1,root);}
}
int LCA(int a,int b){if(dep[a]<dep[b]) swap(a,b);for(int i=log(D)/log(2);i>=0;i--){if(dep[fa[a][i]]>=dep[b]) a=fa[a][i];}if(a==b) return a;for(int i=log(D)/log(2);i>=0;i--){if(fa[a][i]!=fa[b][i]){a=fa[a][i];b=fa[b][i];}}return fa[a][0];
}
int main(){memset(h,-1,sizeof(h));scanf("%d%d%d",&n,&m,&s);fa[s][0]=s;for(int i=1;i<=n-1;i++){int x,y;scanf("%d%d",&x,&y);Add(x,y);Add(y,x);}Dfs(s,1,0);for(int i=1;i<=m;i++){int a,b;scanf("%d%d",&a,&b);printf("%d\n",LCA(a,b));}return 0;
}

ybt 1552【例 1】点的距离

随便选一个点当作树根,然后在跳的时候记录跳的步数即可。

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e5+10;
struct Node{int to,nxt;
}e[2*maxn];
int n,m,s,D;
int tot,h[maxn],dep[maxn],fa[maxn][20];
void Add(int u,int v){tot++;e[tot].to=v;e[tot].nxt=h[u];h[u]=tot;
}
void Dfs(int root,int cur,int fath){fa[root][0]=fath;D=max(D,cur);dep[root]=cur;for(int i=1;i<=log(dep[root])/log(2);i++){fa[root][i]=fa[fa[root][i-1]][i-1];}for(int i=h[root];i!=-1;i=e[i].nxt){int v=e[i].to;if(v!=fath) Dfs(v,cur+1,root);}
}
int LCA(int a,int b){int ans=0;if(dep[a]<dep[b]) swap(a,b);for(int i=log(D)/log(2);i>=0;i--){if(dep[fa[a][i]]>=dep[b]){a=fa[a][i];ans+=pow(2,i);} }if(a==b) return ans;for(int i=log(D)/log(2);i>=0;i--){if(fa[a][i]!=fa[b][i]){a=fa[a][i];b=fa[b][i];ans+=2*pow(2,i);}}return ans+2;
}
int main(){memset(h,-1,sizeof(h));scanf("%d",&n);fa[s][0]=s;for(int i=1;i<=n-1;i++){int x,y;scanf("%d%d",&x,&y);Add(x,y);Add(y,x);}scanf("%d",&m);Dfs(1,1,0);for(int i=1;i<=m;i++){int a,b;scanf("%d%d",&a,&b);printf("%d\n",LCA(a,b));}return 0;
}
http://www.jsqmd.com/news/79302/

相关文章:

  • 2026大专建筑工程必看!这些证书让你找工作不踩雷!
  • 【笔记】龟速乘与快速幂
  • 这的确很棒
  • GitLab与DeepSeek协同实现MR自动评审实践指南
  • 2025最新家电安装平台TOP5评测!优质家电服务公司深度解析,安装数智化赋能+全国覆盖权威榜单发布,重构家居服务生态 - 全局中转站
  • CF 口胡记录
  • 产品经理资源合集
  • 行测教程资源合集
  • 【笔记】二分
  • 基于心电信号时空特征的QRS波检测算法的Matlab 2022a仿真
  • 基于springboot的档案数字化管理系统
  • 2025最新家电维修/家电安装/租房/家政保洁/找房服务推荐——速达优家(微信小程序),一站式解决居家难题,优选平台实力护航 - 全局中转站
  • B样条曲线根据曲率极值进行分段速度规划的方法介绍
  • Flutter Provider 状态管理深度解析与开源鸿蒙 ArkUI 状态管理对比
  • mysql重装,3306端口占用问题解决
  • mysql重装,3306端口占用问题解决
  • 揭秘大规模供应链优化:自动化决策系统如何高效运转
  • 2026转行IT,学Python还是Java更好找工作?
  • XTOOL D9S 1-Year Update Service: Keep Your Tool Updated for European/American Vehicles
  • 伊沙佐米:治疗多发性骨髓瘤的靶向药物解析【海得康】
  • 【笔记】最近公共祖先 Tarjan 算法
  • 2025 最新家政保洁平台服务商 TOP5 评测!优质家政保洁服务公司深度解析,重构家居生活服务新生态 - 全局中转站
  • Notepad(文本编辑器)v3.6.30绿色官方版
  • Spring的DI依赖注入(配置文件方式)
  • Office Tool Plus v10.29.50 office安装激活一条龙
  • 在写小故事(实则是高中回忆录)
  • 【题解】Luogu P1081 [NOIP2012 提高组] 开车旅行
  • 2025年AI图文创作神器01Agent:3步解决‘死图‘痛点,效率提升300%
  • 2025年AI图文创作神器01Agent:3步解决‘死图‘痛点,效率提升300%
  • 如何编写优美的代码:从工匠到艺术家的修炼之路