時間和空間複雜度分別是 o((n+q)logn) 和 o(nlogn) 。
1.dfs求每個節點的深度
2.倍增跳躍祖先節點預處理
3.如果兩節點不在同一高度,則讓較深的高度u跳躍到較淺的高度v來。
4.兩個節點同時跳躍,先從大的跳躍幅度開始。
5.直到最後跳躍到最近公共祖先的下一層為止
#include
#include
#include
#include
#include
using namespace std;
const
int maxn=
1e3+5;
int father[maxn][40
]=;vector<
int> g[maxn]
;int depth[maxn]=;
int n,m;
int visit[maxn]
;int indeg[maxn]
;void
dfs(
int u)}}
//深搜,求出各點的深度
voidbz(
)}}int
lca(
int u,
int v )
if(u == v)
return v;
//如果深度一樣時,兩個點相同,則說明u在v的下面,直接返回。
for(
int i=
29;i>=
0;i--
)//注意,這裡沒有直接跳出,而是反覆跳到最近公共祖先的下一層為止才退出
}return father[u][0
];//再往上走一層就是最近公共祖先
}int
main()
scanf
("%d%d"
,&x,
&y);
int root=0;
for(
int i=
1;i<=n && root==
0;i++
)dfs
(root);bz
();int ans =
lca(x,y)
;printf
("%d\n"
,ans)
;return0;
}
輸入樣例
5 41 3
2 33 4
3 54 5
輸出樣例
3解釋:
題目有5個頂點,4條邊,查詢4節點和5節點的最近公共祖先
輸出結果為3
離線演算法:先讀入所有查詢,在一次遍歷中,把所有詢問一次性解決。
時間複雜度:o(n
+q
)o(n+q)
o(n+q)
p3379 【模板】最近公共祖先(lca)
有3個測試點沒過,懶得改了,等以後有時間了再修改吧。
#include
using namespace std;
const
int maxn =
5e+5
;int f[maxn]
;bool vis[maxn]
;vector<
int> g[maxn]
,q[maxn]
;struct qnodequery[maxn]
;void
init()
}int
find
(int x)
void
dfs(
int u)
}else}}
for(
auto v : g[u])}
intmain()
for(
int i=
1;i<=m;i++
)dfs
(s);
for(
int i=
1;i<=m;i++
)return0;
}
最近公共祖先 python 最近公共祖先
lca演算法樸素演算法 也就是我們所說的暴力演算法,大致的思路是從樹根開始,往下迭代,如果當前結點比兩個結點都小,那麼說明要從樹的右子樹中找 相反則從左子樹中查詢 直到找到乙個結點在當前結點的左邊,乙個在右邊,說明當前結點為最近公共祖先,如果乙個結點是另外乙個結點的祖先,那麼返回前面結點的父親結點即...
最近公共祖先 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,表示詢問...