倍增法求lca

2021-09-10 01:48:15 字數 861 閱讀 6720

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...