在二叉樹中找到兩個節點的最近公共祖先(再高階)
給定一棵二叉樹,多次給出這棵樹上的兩個節點 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 行...