樹上倍增求LCA(最近公共祖先)

2021-07-06 03:29:32 字數 1479 閱讀 9911

前幾天做faebdc學長出的模擬題,第三題最後要倍增來優化,在學長的講解下,嘗試的學習和編了一下倍增求lca(我能說我其他方法也大會嗎?。。)
倍增求lca:

father【i】【j】表示節點i往上跳2^j次後的節點

可以轉移為

father【i】【j】=father【father【i】【j-1】】【j-1】

(此處注意迴圈時先迴圈j,再迴圈i)

然後dfs求出各個點的深度depth

整體思路:

先比較兩個點的深度,如果深度不同,先讓深的點往上跳,淺的先不動,等兩個點深度一樣時,if 相同 直接返回,if 不同 進行下一步;如果不同,兩個點一起跳,j從大到小列舉(其實並不大),如果兩個點都跳這麼多後,得到的點相等,兩個點都不動(因為有可能正好是lca也有可能在lca上方),知道得到的點不同,就可以跳上來,然後不斷跳,兩個點都在lca下面那層,所以再跳1步即可,當father【i】【j】中j=0時即可,就是lca,返回值結束

感謝sunshinezff學長的編碼糾錯幫助

下面是**:「`

#include

#include

#include

#include

#include

using

namespace

std;

vector

g[100010];

int father[100010][40]=;

int depth[100010]=;

int n,m;

bool visit[10010]=;

int root;

void dfs(int u)

}

}//深搜出各點的深度,存在depth中

void bz()

//倍增,處理father陣列,詳情參照上述講解

int lca(int u,int v)

//保證深度大的點為u,方便操作

int dc=depth[u]-depth[v];

int i;

for (i=0;i<30;i++)//值得注意的是,這裡需要從零列舉

//上述操作先處理較深的結點,使兩點深度一致

if (u==v) return u;//如果深度一樣時,兩個點相同,直接返回

for (i=29;i>=0;i--)

}u=father[u][0];//上述過程做完,兩點都在lca下一層,所以走一步即可

return u;

}int main()

depth[root]=1;

dfs(root);

bz();

int x,y;

scanf("%d%d",&x,&y);

printf("%d",lca(x,y));

return

0;

}

倍增法求lca(最近公共祖先)

基本上每篇部落格都會有參考文章,一是彌補不足,二是這本身也是我學習過程中找到的覺得好的資料 大致上演算法的思路是這樣發展來的。想到求兩個結點的最小公共祖先,我們可以先把兩個的深度提到同一水平,在一步一步往上跳,直到兩個結點有了乙個公共祖先,依照演算法流程,這就是least common ancest...

LCA 最近公共祖先 (倍增演算法)

首先了解一下我們 最近公共祖先 e和g的lca為a l和j的lca為d k和f的lca為b 然後 倍增 用到了二進位制和 dp 的思想 倍增 就是 1 2 4 8 16 任何乙個數 都是可以右 這些數相加得到的。了解一下二進位制 首先 定義 fa i j 為 從 i 節點 向上走 2 j 個節點,d...

最近公共祖先 LCA 倍增演算法

樹上倍增求lca lca指的是最近公共祖先 least common ancestors 如下圖所示 4和5的lca就是2 那怎麼求呢?最粗暴的方法就是先dfs一次,處理出每個點的深度 然後把深度更深的那乙個點 4 乙個點地乙個點地往上跳,直到到某個點 3 和另外那個點 5 的深度一樣 然後兩個點一...