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

2021-10-12 18:25:11 字數 1154 閱讀 1359

直接暴力搜尋參考:

普通搜尋每次查詢都需要

樸素演算法是一層一層往上找,倍增的話直接預處理出乙個

具體做法是:維護乙個

的關係來線性求出這個陣列

int anc[n][31];

int dep[n]; // 記錄節點深度

void dfs(int u, int parent)

for(int i = 0; i < g[u].size(); i++)

}

沒錯就是這麼簡單。

然後在求最近公共祖先的時候我們還需要幹一件事情,就是讓兩個節點的深度相等,也就是讓他們走到同乙個起跑線上,有了

陣列之後就能夠很快速的幹這事了:

void swim(int &u, int &v) 

}

注意:

1. swim過後如果u == v那麼說明當前節點就是他們的最近公共節點。

2. 因為更改了u和v, 所以一定要引用傳參。

最後就是如何求lca了,基本上就是重複選擇乙個合適的

的值去不斷逼近:

int lca(int u, int v) 

return -1; //沒找到

}

先用dfs將節點的深度和尤拉序列求出來。然後再在這個序列裡面進行rmq區間最值查詢。

尤拉序列:節點第一次遍歷和回溯時候遍歷按順序記錄下來,總共有

個。尤拉序:把節點

在尤拉序列第一次出現的位置編號記錄下來,如

例如:

上圖的尤拉序為: 3 → 5 → 6 → 5 → 2 → 7 → 2 → 4 → 3 → 1 → 0 → 1 → 8

對應的深度資訊: 0 → 1 → 2 → 1 → 2 → 3 → 2 → 4 → 0 → 1 → 2 → 1 → 2

可以很清晰的看到,從

走到 一定會經過他們的lca,也一定不會經過他們lca節點的父節點。 加上他們之間的lca節點的深度肯定是這段序列裡面最淺的那乙個,因此我們可以通過簡單的求區間最值的演算法求出兩個節點的lca。

通常的rmq演算法可以採用st離線演算法或者線段樹。這裡就不展開講了。

最近公共祖先 最近公共祖先(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的樹,求某兩個點的最近公共祖先。思路 預處理出每個點的深度再一...

最近公共祖先LCA

最近公共祖先 lca 演算法思想 對一棵樹進行深搜回溯標號,那麼兩個節點的最近公共祖先就是兩個節點第一次標號之間深度最小 非標號,因為回溯會增大那個節點,雖然該節點第一次標號很小 的那個對應的節點 poj1330 include include include include include inc...