在二叉樹中找到兩個節點的最近公共祖先 再高階

2021-10-23 21:53:23 字數 2267 閱讀 7014

在二叉樹中找到兩個節點的最近公共祖先(再高階)

給定一棵二叉樹,多次給出這棵樹上的兩個節點 o1 和 o2,請對於每次詢問,找到 o1 和 o2 的最近公共祖先節點。

輸入描述:

第一行輸入兩個整數 n 和 root,n 表示二叉樹的總節點個數,root 表示二叉樹的根節點。

以下 n 行每行三個整數 fa,lch,rch,表示 fa 的左兒子為 lch,右兒子為 rch。(如果 lch 為 0 則表示 fa 沒有左兒子,rch同理)

第 n+2 行輸入乙個整數 m,表示詢問的次數。

以下 m 行每行兩個節點 o1 和 o2。

輸出描述:

對於每組詢問每行輸出乙個整數表示答案。

示例1輸入

8 1

1 2 3

2 4 5

4 0 0

5 0 0

3 6 7

6 0 0

7 8 0

8 0 0

44 5

5 26 8

5 8

輸出
223

1

備註:

1 ≤n

≤105

1 \leq n \leq 10^5

1≤n≤1051≤

m≤10

51 \leq m \leq 10^5

1≤m≤1051≤

fa,l

ch,r

ch,r

oot,

o1,o

2≤

n1 \leq fa,lch,rch,root,o_1,o_2 \leq n

1≤fa,l

ch,r

ch,r

oot,

o1​,

o2​≤

n o 1≠

o2

o_1 \neq o_2

o1​​=

o2​題解:

離線解法

tarjan + 並查集,通過並查集維護兩個節點的最近公共祖先。參考

注意:此題測試資料出現森林的情況,debug了個寂寞。。。

st/倍增/樹鏈剖分,以後用到再說吧,不在搞競賽了,應該用不上。

**:

#include

#include

#include

using

namespace std;

const

int n =

100010

;typedef pair<

int,

int> pii;

vector<

int> g[n]

;vector<

int> q[n]

;int fa[n]

;bool vis[n]

;int n, rt;

int _fa, lch, rch;

int m;

int o1[n]

, o2[n]

;int deg[n]

;mapint> ret;

int_find

(int x)

void

_merge

(int u,

int v)

void

lca(

int root)

} sze = q[root]

.size()

;for

(int i =

0; i < sze;

++i);if

(!ret.

count

(pii)

) ret[pii]

=_find

(q[root]

[i]);}

}}intmain

(void)if

(rch)

}scanf

("%d"

,&m)

;for

(int i =

0; i < m;

++i)

for(

int i =

1; i <= n;

++i)if(

!deg[i]

)lca

(i);

for(

int i =

0; i < m;

++i)

;printf

("%d\n"

, ret[pii]);

}return0;

}

在二叉樹中找到兩個節點的最近公共祖先 I

給定一棵二叉樹的頭節點 head,以及這棵樹中的兩個節點 o1 和 o2,請返回 o1 和 o2 的最 近公共祖先節點。說明 o1和o2要麼同時都在二叉樹上,要麼同時都不在二叉樹上。後序遍歷二叉樹,假設遍歷到的當前節點為 cur。因為是後序遍歷,所以 先處理 cur 的兩棵子樹。假設處理 cur 左...

在二叉樹中找到兩個節點的最近公共祖先 高階

在二叉樹中找到兩個節點的最近公共祖先 高階 給定一棵二叉樹,多次給出這棵樹上的兩個節點 o1 和 o2,請對於每次詢問,找到 o1 和 o2 的最近公共祖先節點。輸入描述 第一行輸入兩個整數 n 和 root,n 表示二叉樹的總節點個數,root 表示二叉樹的根節點。以下 n 行每行三個整數 fa,...

演算法實現 在二叉樹中找到兩個節點的最近公共祖先

該題目來自一次面試。在二叉樹中找到兩個節點的最近公共祖先 高階 給定一棵二叉樹,多次給出這棵樹上的兩個節點 o1 和 o2,請對於每次詢問,找到 o1 和 o2 的最近公共祖先節點。輸入描述 第一行輸入兩個整數 n 和 root,n 表示二叉樹的總節點個數,root 表示二叉樹的根節點。以下 n 行...