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

2022-07-16 16:36:11 字數 1686 閱讀 5193

如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。

輸入格式:

第一行包含三個正整數n、m、s,分別表示樹的結點個數、詢問的個數和樹根結點的序號。

接下來n-1行每行包含兩個正整數x、y,表示x結點和y結點之間有一條直接連線的邊(資料保證可以構成樹)。

接下來m行每行包含兩個正整數a、b,表示詢問a結點和b結點的最近公共祖先。

輸出格式:

輸出包含m行,每行包含乙個正整數,依次為每乙個詢問的結果。

輸入樣例#1: 複製

5 5 4

3 12 4

5 11 4

2 43 2

3 51 2

4 5

輸出樣例#1: 複製

441

44

時空限制:1000ms,128m

資料規模:

對於30%的資料:n<=10,m<=10

對於70%的資料:n<=10000,m<=10000

對於100%的資料:n<=500000,m<=500000

樣例說明:

該樹結構如下:

第一次詢問:2、4的最近公共祖先,故為4。

第二次詢問:3、2的最近公共祖先,故為4。

第三次詢問:3、5的最近公共祖先,故為1。

第四次詢問:1、2的最近公共祖先,故為4。

第五次詢問:4、5的最近公共祖先,故為4。

故輸出依次為4、4、1、4、4。

先存下板子,之後再寫一篇lca的學習筆記

1 #include 2 #include 3

using

namespace

std;

4const

int n = 5e5+50;5

intn,m,s;

6int head[n],dep[n],p[n][22];7

intlg[n];

8struct

node;

11 node edge[n*2

];12

int cnt=0;13

void add(int u,int

v)18

void

init()22}

23void dfs(int u,int

fa)29

for(register int i=head[u];i;i=edge[i].net)34}

35int lca(int x,int

y)39

while(dep[x]>dep[y])

42if(x==y)

43return

x;44

for(register int k=lg[dep[x]];k>=0;k--)49}

50return p[x][0

];51}52

intmain()

5362

init();

63 dfs(s,0

);64

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

70//

cout << "hello world!" << endl;

71return0;

72 }

view code

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

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

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...