lca
http://unbelievable.ycool.com/post.982865.html
有两种方法的... 这里先搞定一种方法吧...
d[i] 表示 i节点的深度
p[i,j] 表示 i 的 2^j 倍祖先
那么就有一个递推式子 p[i,j]=p[p[i,j-1],j-1]
这样子 一个 o(n log n) 的预处理 求出 每个节点的 2^k 的祖先
然后 对于每一个 询问的点对a b 的最近公共祖先 就是:
先判断是否 d[a]>d[b] 如果是的话就交换一下(保证 a 的深度小于 b 方便下面的操作)
然后把b 调到与a 同深度
同深度以后再 把a b 同时往上调(dec(j)) 调到有一个最小的j 满足 p[a,j]=p[b,j] (a b 是在不断更新的)
最后再把 a b 往上调 (a=p[a,0] b=p[b,0]) 一个一个向上调 直到 a=b
这时 a or b 就是他们的 最近公共祖先
{建树时 p[i,0]:=father[i] 同时记录好d[i] } procedure prepare; var k, i, j : longint; begin k:=1; j:=0; while k<n do begin inc(j); k:=k+k; for i:=1 to n p[i,j]:=p[p[i,j-1],j-1]; end; power:=k; limit:=j; end; function lca(a, b : longint): longint; |