最近公共祖先 倍增算法-天天快播报

来源:2023-05-01 20:19:27    时间:博客园


(资料图片)

求最近公共祖先(Lowest Common Ancestor,LCA)例题:洛谷P3379 【模板】最近公共祖先(LCA)https://www.luogu.com.cn/problem/P3379

基本思路就是先用倍增把两点升到同一深度,然后倍增来找最近公共祖先。其中fa数组是关键

#include#include#define forup(i,l,r) for(int i=l;i<=r;i++)#define fordown(i,l,r) for(int i=r;i>=l;i--)using namespace std;const int N =5e5+5;int dep[N],fa[N][20];//fa[u][i]指从u向上跳2^i个结点到达的祖先结点 //2^20大约为一百万,具体为1048576 vector child[N];//结点所连的结点(这里包括了父节点) int read(){int n=0;char m=getchar();while(m<"0"||m>"9") m=getchar();while(m>="0"&&m<="9"){n=(n<<1)+(n<<3)+(m^"0");m=getchar();}return n;}void dfs(int father,int u)//作用是初始化dep和fa数组 {dep[u]=dep[father]+1;fa[u][0]=father;forup(i,1,19)//跳2^i个相当于是先跳2^(i-1)到fa[u][i-1],然后再往上跳2^(i-1)到fa[u][i] {fa[u][i]=fa[fa[u][i-1]][i-1];}for(int v:child[u])//对子节点进行访问 {if(v!=father) dfs(u,v);}}int lca(int u,int v){if(u==v) return u;//特判 if(dep[u]=dep[v])//dep的差=2^x1+2^x2+...+2^xn,故一定可以让u跳到和v同层的地方 {u=fa[u][i]; }}if(u==v) return u;//特判二度 fordown(i,0,19){if(fa[u][i]!=fa[v][i])//让u,v跳到最近公共祖先的下一个,原理同上一个for {u=fa[u][i]; v=fa[v][i];}}return fa[u][0];}int main(){int n,m,root;n=read(),m=read(),root=read();forup(i,1,n-1)//建树{int u,v;u=read(),v=read();child[v].push_back(u);child[u].push_back(v);}dfs(0,root);//作用是初始化dep和fa数组 forup(i,1,m)//查询 {int u,v;u=read(),v=read();cout<

另外,当深度对应的结点数不那么明朗的时候比如不清楚n是2的多少次方,或者需要优化的时候,可以预处理一个lg数组来判断需要最多跳多少层,注意lg里面是深度或深度差递推公式为lg[i]=lg[i-1]+((1<<(lg[i-1]+1))==i)

#include#include#define forup(i,l,r) for(int i=l;i<=r;i++)#define fordown(i,l,r) for(int i=r;i>=l;i--)using namespace std;const int N =5e5+5;int dep[N],fa[N][20];//fa[u][i]指从u向上跳2^i个结点到达的祖先结点 //2^20大约为一百万,具体为1048576 int lg[N];//lg为log2(n)vector child[N];//结点所连的结点(这里包括了父节点) int read(){int n=0;char m=getchar();while(m<"0"||m>"9") m=getchar();while(m>="0"&&m<="9"){n=(n<<1)+(n<<3)+(m^"0");m=getchar();}return n;}void dfs(int father,int u)//作用是初始化dep和fa数组 {dep[u]=dep[father]+1;fa[u][0]=father;forup(i,1,lg[dep[u]])//跳2^i个相当于是先跳2^(i-1)到fa[u][i-1],然后再往上跳2^(i-1)到fa[u][i] {fa[u][i]=fa[fa[u][i-1]][i-1];}for(int v:child[u])//对子节点进行访问 {if(v!=father) dfs(u,v);}}int lca(int u,int v){if(u==v) return u;//特判 if(dep[u]dep[v]) {u=fa[u][lg[dep[u]-dep[v]]];//2^lg始终小于等于dep的差 }if(u==v) return u;//特判二度 fordown(i,0,lg[dep[u]]){if(fa[u][i]!=fa[v][i])//让u,v跳到最近公共祖先的下一个{u=fa[u][i]; v=fa[v][i];}}return fa[u][0];}int main(){int n,m,root;n=read(),m=read(),root=read();forup(i,2,n){lg[i]=lg[i-1]+((1<<(lg[i-1]+1))==i);//在此之前i都是处于[2^lg[i-1],2^lg[i])之间的数,即2^lg[i-1]*2>i } forup(i,1,n-1){int u,v;u=read(),v=read();child[v].push_back(u);child[u].push_back(v);}dfs(0,root);//作用是初始化dep和fa数组 forup(i,1,m)//查询 {int u,v;u=read(),v=read();cout<

至于为什么不直接用c++自带的log函数,因为log比20快但是比lg数组慢

参考:https://www.cnblogs.com/dx123/p/16320461.htmlhttps://blog.csdn.net/weixin_45697774/article/details/105289810次方表:https://blog.csdn.net/weixin_44827418/article/details/106355287

关键词:

文章推荐

  • 赏传统年俗逛非遗庙会 铜官窑古镇重温传统民俗年

    中新网长沙2月6日电 (潘杏琼)在多地倡导就地过年的环境下,位于长沙市城北的铜官窑古镇景区,从1月24日至2月15日举行中国年·湖湘味·铜官

    中新网 2022-02-07
  • 哈尔滨铁路迎节后返程高峰 推出复工专列服务

    中新网哈尔滨2月6日电 (周晓舟 记者 史轶夫)中国铁路哈尔滨局有限公司6日发布消息,哈尔滨铁路迎来春节后返程客流高峰,6日至7日预

    中新网 2022-02-07
  • 冬奥动车组设5G超高清演播室 “瑞雪迎春”号智能化人性化结合

    中新网北京2月6日电 (记者 刘文曦)在时速350公里的高铁列车上首设5G超高清演播室,为北京冬奥会量身定制的新型奥运版智能复兴号动车组瑞

    中新网 2022-02-07
  • 中欧班列“签证官”:日行10公里 用锤子“听诊”

    (新春走基层)中欧班列“签证官”:日行10公里 用锤子“听诊”  中新网郑州2月6日电 题:中欧班列“签证官”:日行10公里,用锤子“

    中新网 2022-02-07
  • 西湖守兰人的春节美丽故事:花苞为伴 手留余香

    中新网杭州2月6日电 (记者 谢盼盼)守望花苞,这是西湖守兰人许晔的春节故事,春节正是兰花花苞开花的重要时期。  今年春节里,浙江

    中新网 2022-02-07
  • 广告

    X 关闭

    X 关闭

  • 众测
  • more+

    京张高铁每日开行17对冬奥列车

      京张高铁每日开行17对冬奥列车  预计冬奥服务保障期运送运动员、技术官员、持票观众等20万人次  2月6日,2022北京新闻中心举行“北

    北京冬奥会开幕式上 小学生朱德恩深情演绎《我和我的祖国》

      北京冬奥会开幕式上 小学生朱德恩深情演绎《我和我的祖国》  9岁小号手苦练悬臂吹响颂歌  2月4日晚,在北京冬奥会开幕式上,9岁的

    2022北京冬奥会开幕式这19首乐曲串烧不简单

      多名指挥家列曲目单 再由作曲家重新编曲 本报专访冬奥开幕式音乐总监赵麟  开幕式这19首乐曲串烧不简单  “二十四节气”倒计时、

    “一墩难求” 冰墩墩引爆购买潮

    设计师:没想到冰墩墩成爆款一墩难求冰墩墩引爆购买潮 北京冬奥组委:会源源不断供货北京冬奥会吉祥物冰墩墩近日引爆购买潮,导致一墩难求