LCA最近公共祖先

2022-06-17 15:30:20 字數 2431 閱讀 6805

原來學習最小生成樹的時候寫了道題,發現得用最近公共祖先迫於無奈便學了lca(不過確實很有用)

lca主要基於一種倍增的思想,和st表很像,通過預處理資料來花費空間換取時間。

要想學習怎麼求lca首先要學習lca是什麼。

在一顆數中,比如說圖中的4和5,那麼他們的最近公共祖先便是2。

如果是2和3他們的最近公共祖先便是1,而2和4的最近公共祖先是2本身,所以最近公共祖先也可以是自己。

那麼要如何來求呢。最樸素的做法是用dfs進行搜尋查詢,但這樣的時間複雜度太高了。

於是就出現了這種基於倍增的lca。

這裡盜用一張洛谷的圖,上面那圖太小了

------------恢復內容開始------------

原來學習最小生成樹的時候寫了道題,發現得用最近公共祖先迫於無奈便學了lca(不過確實很有用)

lca主要基於一種倍增的思想,和st表很像,通過預處理資料來花費空間換取時間。

要想學習怎麼求lca首先要學習lca是什麼。

在一顆數中,比如說圖中的4和5,那麼他們的最近公共祖先便是2。

如果是2和3他們的最近公共祖先便是1,而2和4的最近公共祖先是2本身,所以最近公共祖先也可以是自己。

那麼要如何來求呢。最樸素的做法是用dfs進行搜尋查詢,但這樣的時間複雜度太高了。

於是就出現了這種基於倍增的lca。

這裡盜用一張洛谷的圖,上面那圖太小了

比如說我們想求17和8的公共祖先,我們便要考慮將17和8給弄到同一層(即樹的深度,第一層的深度是1)

17比8的深度要深,所以得先把17往上面爬。

如果一層一層的爬,那效率便太低了,所以我們便考慮一此直接爬2^n層。

比如這裡17爬到10,我們直接爬2^1層,便不用爬兩次了。

爬到相同的層數之後,我們還要繼續爬,不過這時是兩邊一起爬相同的層數,也是一次爬2^n層,一直到爬到相同的節點便ok了,這時的這個節點便是我們要找的最近公共祖先。

講了那麼多現在最重要的便是如何實現了。

話不多說先上**再講解(這裡是資料的預處理階段採用dfs)

void dfs(int here,int

fa)

這步預處理是演算法的核心,而這步的核心便是對二維陣列f[i][j]的操作

這個陣列中儲存的數代表著i這個節點往上跳2^j步所到的節點。

預處理完了便是查詢了。

int lca(int x,int

y) }//讓x和y一同往上跳,如過跳到下一層他們就相同就不跳了

return f[x][0

];因為下一層才相同,所以return x往上跳2^0層

}

這樣lca大概就講完了,最後附上全部**

#include#include

#include

#include

#include

#define maxx 1000005

using

namespace

std;

int head[maxx], now = 0, n, m, lg[maxx], f[maxx][32

], depth[maxx], vis[maxx], p;

struct

edge a[maxx*2

];void add_edge(int at, int

to)

void swap(int& x, int&y)

void dfs(int here,int

fa)

for (int i = head[here]; i; i =a[i].nex)

if(!vis[a[i].to])

dfs(a[i].to, here);

}int lca(int x,int

y) }

return f[x][0];}

intmain()

lg[0] = -1

;

for (int i = 1; i <= n; i++)

dfs(p, 0);

for (int i = 1; i <= m; i++)

return0;

}

**比較醜,多多包含

最近公共祖先 LCA 最近公共祖先

直接暴力搜尋參考 普通搜尋每次查詢都需要 樸素演算法是一層一層往上找,倍增的話直接預處理出乙個 具體做法是 維護乙個 的關係來線性求出這個陣列 int anc n 31 int dep n 記錄節點深度 void dfs int u,int parent for int i 0 i g u size...

最近公共祖先 最近公共祖先(LCA)

如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。輸入格式 第一行包含三個正整數n m s,分別表示樹的結點個數 詢問的個數和樹根結點的序號。接下來n 1行每行包含兩個正整數x y,表示x結點和y結點之間有一條直接連線的邊 資料保證可以構成樹 接下來m行每行包含兩個正整數a b,表示詢問...

LCA 最近公共祖先

定義 對於有根樹t的兩個結點u v,最近公共祖先lca t,u,v 表示乙個結點x,滿足x是u v的祖先且x的深度盡可能大。另一種理解方式是把t理解為乙個無向無環圖,而lca t,u,v 即u到v的最短路上深度最小的點。現在給定乙個根為1的樹,求某兩個點的最近公共祖先。思路 預處理出每個點的深度再一...