最近公共祖先 LCA
阿新 • • 發佈:2019-01-04
一、基本演算法
1、 Tarjan演算法基於深度優先搜尋的框架,對於新搜尋到的一個節點,首先建立有這個節點構成的集合,再對當前節點的每一個子樹進行搜尋,每搜尋完一個子樹,則確定子樹內的LCA詢問都已解決。其他的LCA詢問的結果必然在這個子樹之外,這時把子樹所形成的集合與當前節點的集合合併,並將當前節點設為這個集合的祖先。之後繼續搜尋下一棵子樹。
2、虛擬碼:
(1)建立以u為代表的集合。
(2)遍歷與u相連的節點v,如果v沒有被訪問過,對於v使用LCA演算法,結束後,將v的集合併入u的集合。
(3)對於與u有關的詢問(u, v), 如果v被訪問過,則結果就是v所在的集合的代表元素。
3、程式碼:
int p[MAXX]; int head[MAXX]; //前向星 int qhead[MAXX]; // 表示詢問 struct node { int to; int lca; int next; }; node edge[MAXX]; // 邊的資訊 node qedge[MAXX]; // 表示詢問 int Find(int x) { if (p[x] != x) p[x] = Find(p[x]); return p[x]; } bool vis[MAXX]; void LCA(int u) { p[u] = u; int k; vis[u] = true; for (k=head[u]; k!=-1; k=edge[k].next) { if (!vis[edge[k].to) { LCA(edge[k].to); p[edge[k].to] = u; } } for (k=qhead[u]; k!=-1; k = qedge[k].next) { if (vis[qedge[k].to]) { qedge[k].lca = Find(qedge[k].to); qedge[k^1].lca = qedge[k].lca; } } }