設樹上有兩點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在相同一鏈上,除此以外兩點毫不會在同一條鏈上。