LCA 最近公共祖先
LCA 最近公共祖先
定义
给定一颗有根数,若节点\(z\)既是节点\(x\)的祖先,也是节点\(y\)的祖先,则称\(z\)是\(x\)和\(y\)的公共祖先。在\(x\)、\(y\)的所有公共祖先中,深度最大的一个称为\(x\),\(y\)的最近公共祖先,记为\(LCA(x,y)\)
如上图中,\(LCA(6,8)=1\),\(LCA(8,9)=4\),\(LCA(7,8)=7\)
算法
求\(LCA\)有三种算法:
- 向上标记法
- 树上倍增法
- 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)\)
- 不妨设 \(d[x]\ge d[y]\) (否则交换\(x\)与\(y\)),
- 寻找一个\(k\),使其满足 \(d[F[x,k]]\le d[y]\) 且\(k\)最大。
此时令 \(x=F[x,k]\) ,让\(x\)不断向上走,直到 \(d[x]=d[y]\) ,即\(x\)与\(y\)深度相等,进行第三步。 - 如果 \(x=y\) 即\(y\)是\(x\)祖先,如上图中\(LCA(7,8)=7\),此时便找到了\(LCA(x,y)=x\)
- 寻找一个\(k\),使其满足 \(d[F[x,k]] = d[F[y,k]] F[x,k] \ne F[y,k]\) 且\(k\)最大。
重复此步直到寻找不到这样的\(k\)
这一步在不断地将\(x\)与\(y\)向上走,保持深度一致,但不相遇(即不相等),走到不能再向上走为止 - 此时\(LCA(x,y)\)就是\(F[x,0]\)
Tarjan法
留白