LCA 最近公共祖先

LCA 最近公共祖先

定义

给定一颗有根数,若节点\(z\)既是节点\(x\)的祖先,也是节点\(y\)的祖先,则称\(z\)\(x\)\(y\)的公共祖先。在\(x\)\(y\)的所有公共祖先中,深度最大的一个称为\(x\)\(y\)的最近公共祖先,记为\(LCA(x,y)\)

image
如上图中,\(LCA(6,8)=1\),\(LCA(8,9)=4\),\(LCA(7,8)=7\)

算法

\(LCA\)有三种算法:

  1. 向上标记法
  2. 树上倍增法
  3. Tarjan算法

向上标记法

\(x\)向上走到根节点,并标记所有经过的节点
\(y\)向上走到根节点,当第一次遇到已标记的节点时,就找到了\(LCA(x,y)\)
对于每个询问,向上标记法的时间复杂度最坏为$ \Theta(n) $,但该算法常数大,面对大量询问时易TLE,在算法竞赛中运用较少。

树上倍增法

节点表示


祖先

\(F[x,k]\)\(x\)的距离为\(2^k\)的祖先编号,如在上图中 \(F[8,0]=7 F[8,1]=4\) ,特殊的,若 \(F[x,k]\) 不存在,则令 \(F[x,k]=0\) ,例如 \(F[8,2]=0\)

深度

\(d[x]\)表示节点\(x\)的深度

求LCA


\(LCA(x,y)\)

  1. 不妨设 \(d[x]\ge d[y]\) (否则交换\(x\)\(y\)),
  2. 寻找一个\(k\),使其满足 \(d[F[x,k]]\le d[y]\)\(k\)最大。
    此时令 \(x=F[x,k]\) ,让\(x\)不断向上走,直到 \(d[x]=d[y]\) ,即\(x\)\(y\)深度相等,进行第三步。
  3. 如果 \(x=y\)\(y\)\(x\)祖先,如上图中\(LCA(7,8)=7\),此时便找到了\(LCA(x,y)=x\)
  4. 寻找一个\(k\),使其满足 \(d[F[x,k]] = d[F[y,k]] F[x,k] \ne F[y,k]\)\(k\)最大。
    重复此步直到寻找不到这样的\(k\)
    这一步在不断地将\(x\)\(y\)向上走,保持深度一致,但不相遇(即不相等),走到不能再向上走为止
  5. 此时\(LCA(x,y)\)就是\(F[x,0]\)

Tarjan法

留白

posted @ 2025-03-13 18:51  Kelojonle  阅读(37)  评论(0)    收藏  举报