尋找最近公共祖先演算法(LCA)

2021-05-27 05:54:12 字數 1232 閱讀 9202

最近做乙個功能,需要對場景圖中的多個節點回溯其最近公共祖先,這是乙個常用的應用,搜尋了一下,有tarjan演算法。tarjan演算法是一種離線演算法,它需要一次輸入所有的詢問,然後有根節點開始進行深度優先遍歷(dfs),在深度優先遍歷的過程中,進行並查集(見文章參考鏈結)的操作,同時查詢詢問,返回結果。下面介紹實現**及演算法流程:

#include#includeusing namespace std;  

const int max=17;

int f[max]; //每個節點所屬集合?

int r[max]; //r是rank(秩) 合併

int indegree[max]; //儲存每個節點的入度

int visit[max]; //只有0和1,表示某節點id是否已處理完畢

vectortree[max],qes[max]; //樹,查詢

int ancestor[max]; //祖先集合

void init(int n)

} int find(int n) //查詢n節點所在的集合

//查詢函式,並壓縮路徑

int union(int x,int y)

else if(r[a] == r[b]) //兩秩相等,合併到左邊的秩

else

return 1;

}//合併函式,如果屬於同一分支則返回0,成功合併返回1

void lca(int u)

} return 0;

}

演算法步驟:1 由跟節點開始,進行深度優先遍歷,遍歷到葉子節點,置其對應的visit[i] = 1; 2 將父節點與子節點進行合併(將他們置於同乙個集合,詳細看union**),然後,將集合的祖先置為當前節點。(要注意回溯的過程,一定是保證高層次的) 3 詢問查詢,即qes[u][i],u是查詢節點之一(正好是當前節點),i是另乙個查詢節點,如果i此時已被處理完畢,說明i在u的左邊,那麼i所在集合(並不是像有些文章說的i的父節點,這概念不正確)的祖先一定u,i的最近共同祖先(如果u,i在同一子樹,則很好理解,如果u,i在不同子樹,那麼i所在集合的祖先也是u的祖先(注意回溯,上公升,下降));如果i此時未被處理,說明i在u的右邊,對於u,i的詢問只能跳過,但是對i,u的詢問可以處理。

這個是兩個節點共同祖先的查詢,多個的話就用前兩個的查詢結果與下乙個組成乙個查詢,依次類推。

LCA最近公共祖先演算法

在有根數中,兩個節點u和v的公共祖先中距離最近的那個被稱為最近公共祖先 lca,lowerst common ancestor 用於搞笑計算lca的演算法有許多,在此我們介紹其中的兩種。在下文中,我們都假設節點數為n。1.基於二分搜尋的演算法 記節點v到根的深度為depth v 那麼,如果節點w是u...

最近公共祖先 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,表示詢問...