f[i][j]表示從i這個節點出發,向上走2^j步到達的點(超過了最大深度就返回0)
那麼顯然有
因為相當於是從i點先向上走2^(j-1)步,再走2^(j-1)步。等價於一共走2^j步。
然後求lca就是:先把深度大的那個點往上跳,使兩個點的深度相同。
對應的**:
for(int i=18;i>=0;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
可以把兩點之間的深度差理解為乙個二進位制數。
舉個例子:乙個點深度為3,另乙個點深度為16。那麼深度為16的點向上跳13步它們的深度就相同了。
13轉換成二進位制為1101。那麼這個跳的過程就是先跳(1000)步,再跳(100)步,
然後跳(10)步,發現深度超了,就不會跳。
最後跳(1)步,它們深度就相同了。
之後特判一下這時是否相同。
如果不相同:它們就一起往上跳。
如果發現 f[x][i]==f[y][i] ,那麼說明它們跳到了lca或者是超過了lca,就不跳。(當前深度≤lca深度)
但是如果 f[x][i]!=f[y][i] ,那麼它們一定還都在lca下面,就繼續跳。(當前深度》lca深度)
for(int i=18;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
這裡跳完之後,可以發現,它們一定剛好跳到了lca的下面乙個。(可以把深度想成二進位制思考。)
那麼它們的父親就是lca。
void dfs(int u,int f)
void pre()
倍增法求 LCA
預處理 通過dfs遍歷,記錄每個節點到根節點的距離dist u 深度d u 並求出樹上每個節點i的2 j祖先f i j 求最近公共祖先,根據兩個節點的的深度,如不同,向上調整深度大的節點,使得兩個節點在同一層上,如果正好是祖先結束,否則,將連個節點同時上移,查詢最近公共祖先。include incl...
倍增法求LCA
解決的問題 在一棵樹上求u,v的最近公共祖先。思路 預處理parents陣列和depth陣列,首先使u,v深度相同,一起向上迭代,直至找到相同父節點 倍增法求lca include include include includeusing namespace std define n 100010 ...
倍增法求LCA
預處理 通過dfs遍歷,記錄每個節點到根節點的距離dist u 深度d u init 求出樹上每個節點u的2 i祖先p u i 求最近公共祖先,根據兩個節點的的深度,如不同,向上調整深度大的節點,使得兩個節點在同一層上,如果正好是祖先結束,否則,將連個節點同時上移,查詢最近公共祖先。void dfs...