lca,即樹上兩點之間的公共祖先,求這樣乙個公共祖先有很多種方法:
每次將深度大的點往上移動,直至二者相遇
在o(2n)預處理重鏈之後,每次就將深度大的沿重鏈向上,直至二者在一條鏈上
先記錄所有的詢問,對樹進行一次dfs,對於搜尋到的點u,先將點u往下搜,再將點u與父節點所在集合合併,之後對於它的所有詢問(u,v),若v已被訪問,那麼找v所在集合的祖先e,則e就是u與v的lca
但我們今天要講的是
所謂倍增,就是利用二進位制將冗長的多個相同步驟合併,以實現加速轉移的演算法。
比如快速冪就是乙個經典的例子,將多次乘法通過二進位制合併
下面我們來講講如何利用倍增求lca:
還記得上面的暴力演算法嗎?
暴力演算法是最質樸的東西,卻是所有高階操作的出發點,倍增就是這樣。
我們只需要利用倍增,將往上移動的操作壓縮,就能實現演算法複雜度的優化
我們設f[i][j]表示i節點的第2^j代祖先,這樣f[i][0]就是i的父親,而對於所有j>0,我們有
f[i][j] = f[f[i][j - 1]][j - 1]
怎麼理解呢?
i節點的第2^(j - 1)代祖先的2^(j - 1)祖先就是i的第2^j代祖先
所以我們用o(nlogn)的時間就預處理出了f陣列
void dfs(int u,int fa)
求深度
void cal()
return f[u][0];
} else return u;
}
LCA倍增演算法
一.倍增演算法的前期鋪墊 我們記節點v到根的深度為depth v 那麼如果節點w是節點u和節點v的最近公共祖先的話,讓u往上走 depth u depth w 步,讓v往上走 depth v depth w 步,都將走到節點w。因此,我們首先讓u和v中較深的乙個往上走 depth u depth v...
LCA的倍增演算法
對於兩個節點的lca,根據兩個節點的關係分為一下兩種 一 其中一方是另一方的祖先 那u和v的公共祖先就是是祖先的那一方 二 雙方都不是對方的祖先 u和v的祖先x的深度比u和v小,我們先找出u和v中深度較大的乙個,然後讓其向上跳,直到兩個節點的深度相同,當深度相同時,兩個節點開始同時往上跳,直到兩個節...
lca倍增演算法模板
時間限制 1 sec 記憶體限制 128 mb 提交 244 解決 36 提交 狀態 給一棵樹,節點數為n 1 n 250,000 和q 0 q 100,000 個詢問,對於每個詢問求出所求兩點的最近公共祖先 第一行 節點數n 以下n行,第i 1行 點i的父親節點father i 假定根的父親是0 ...