最近公共祖先是指在有根树中,某两个节点u和v最近的公共祖先
祖先是指当前节点到树根的路径上所有的节点
如果v本身是u的祖先,那么u和v的最近公共祖先就是v
比如G和B的最近公共祖先,B本身就是G的祖先,那么B就是G和B的最近公共祖先
-----------------------------------------------------------------------------------------------------------------------------
可以利用LCA求解树上任意两点之间的距离
求解LCA的方法有很多,包括暴力搜索法,树上倍增法,在线RMQ算法 , 离线Tarjan算法
-------------------------------------------------------------------------------------------------------------------------
暴力搜索法
暴力搜索法有两种思路:
第一种是向上标记法:从u向上一直到根节点,标记所有经过的节点
此时如果v已经被标记,则v就是u和v的最近公共祖先节点
否则v也向上走,第一次遇到已标记的节点,该节点即为LCA(u,v)
第二种是同步前进法:将u和v种深度较深的那个节点向上走到和深度较浅的节点同一深度,然后两个一起向上走,直到走到同一个节点,该节点就是u和v的最近公共最先
如果较深的那个节点u到达和v同一深度时,那个节点正好就是v,那么v节点就是u和v的最近公共祖先节点
暴力搜索法求解LCA , 两种思路的时间复杂度最坏下均为O(n)时间
-------------------------------------------------------------------------------------------------------------------------------
树上倍增法
F[i ,j] 表示 i 的 2j 倍祖先,即 i 节点向根节点走2j 步到达的节点
然后利用ST 表,求解LCA
和前面暴搜中第二种同步前进法一样的,先让深度大的节点y向上走到与x同深度 , 然后x和y一起向上走,和爆搜不一样的是,向上走的按照倍增思想走的,不是一步一步地向上走,因此速度更快
怎么让深度大的节点y向上走到与x同深度呢??
总结:按照增量递减的方式,到达的节点深度比x的深度小时,什么也不做,到达的深度大于等于x深度时,y上移,直到增量为0,此时x,y在同一深度
x和y一起向上走,怎么找到最难公共祖先节点呢??
假设x,y已经到达同一深度,现在一起向上走,假设k=3
1.x和y同时向上走2^3,到达是节点相同,什么也不做
2.减少增量,x,y同时向上走2^2步,此时到达的节点不同,x,y上移 x=F[x][2] , y=F[y][2]
3.减少增量,x,y同时向上走2^1步,此时到达的节点不同,x,y上移 x=F[x][1] , y=F[y][1]
4.减少增量,x,y同时向上走2^0步,此时到达的节点相同,什么也不做
总结:按照增量减少的方式,到达的节点相同时,什么也不做,到达的节点不同时,同时向上移,直到增量为0,此时,x,y的父节点即为公共祖先节点