设树上有两点x、y,要求他们的lca(最近公共祖先)html
一、倍增求LCA:htm
先预处理出树上每一个点的向上2^k的祖先。blog
再看x、y:先把深度深的倍增跳到和深度浅的同样的深度,判断是否在同一点:是,该点即为lca;不是,就将两点一块儿倍增向上跳到最高的不一样的两点,它们的父亲就是lca。get
正确性:数可用二进制表示。io
二、RMQ求LCA:遍历
https://www.luogu.org/blog/hicc0305/solution-p3379二进制
正确性:从f小的点x到f大的点y,通过了:x的一部分(或所有)子树,x到lca的路径,lca到y的路径上的点的一部分(或所有)子树、lca到y的路径。显然,其中深度最浅的只能是lca。co
三、Tarjan求LCA:ps
http://www.javashuo.com/article/p-aivftfcf-ks.htmlab
正确性:由两点间路径的惟一性可知,每一个遍历过的点所在并查集的祖宗就是当前点和这个遍历过的点的lca。(假设先遍历了x,若当前遍历到y,必定是从x回溯到了x和y的lca后再到了y,因为并查集是在回溯时为维护的,当x回溯到lca后x所在并查集就会并到lca所在的并查集,但因为lca尚未回溯到它的父亲,因此它的并查集尚未与它的祖先合并)
注意并查集的合并顺序,应是儿子连向父亲。
四、树链剖分求lca:
将树链预处理出后每次将所在链的链头深度最小的点跳到链头的父亲,直到两点在同一链(链头相等)时深度小的就是lca。
正确性:两点必定能跳至于lca在相同一链上,除此以外两点毫不会在同一条链上。