洛谷 3379 最近公共祖先 LCA 倍增

2021-10-23 16:40:43 字數 2814 閱讀 1777

題目描述

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

輸入格式

第一行包含三個正整數 n,m

,sn,m,s

n,m,

s,分別表示樹的結點個數、詢問的個數和樹根結點的序號。

接下來 n−1

n-1n−

1 行每行包含兩個正整數 x,y

x, y

x,y,表示 x 結點和 y 結點之間有一條直接連線的邊(資料保證可以構成樹)。

接下來 m

mm 行每行包含兩個正整數 a,b

a, b

a,b,表示詢問 a 結點和 b 結點的最近公共祖先。

輸出格式

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

輸入輸出樣例

輸入 #1

1 2 3

輸出 #1

2輸入 #2

1 5 3

輸出 #2

2知識點:lca問題:

定義:基於有根樹最近公共祖先問題

在有根樹t中,詢問乙個距離根最遠的結點x,使得x同時為結點u、v

u、vu、

v的祖先,這個祖先節點即為lca

lcalc

a。同時lca

lcalc

a一定是u、v

u、vu、

v路徑上的點。

解題思路

我們可以有這樣乙個思路,先讓u、v

u、vu、

v中深度大的那個點先往上走,直到兩點深度相同。然後一起往上走,知道兩點相遇,這個點就是lca

lcalc

a。接著我們想,如果我們每次只走一步,顯然單次查詢lca複雜度為o(n

)o(n)

o(n)

。那有沒有在空間合適的條件下更好的演算法呢?——我們可以用倍增 倍增 的思想

想要實現這個演算法,首先我們要記錄各個點的深度和他們2

i2^i

2i級的的祖先,用陣列dep

depde

p表示每個節點的深度,f[i

][j]

f[i][j]

f[i][j

]表示節點i

ii的2

j2^j

2j級祖先。 這樣如果我們需要走k步,那只需要跳o(l

ogn)

o(logn)

o(logn

)次即可。

轉移

這個轉移可以說是演算法的核心之一,意思是i

ii的2

i2^i

2i祖先等於i

ii的2(i

−1)2^(i-1)

2(i−1)

祖先的2(i

−1)2^(i-1)

2(i−1)

祖先 ,也就是走2

j2^j

2j步相當於先走2(j

−1)2^(j-1)

2(j−1)

步再走2(j

−1)2^(j-1)

2(j−1)

步。**如下:

void

dfs(int x,int fa)

預處理完畢後,我們就可以去找它的lca

lcalc

a了,為了讓它跑得快一些,我們可以加乙個常數優化。。。(來自洛谷提高組講義)

for

(int i=

1;i<=n;i++

) lg[i]

=lg[i-1]

+(1<

==i)

;

接下來就是倍增lca

lcalc

a了,按前面說到的我們先把兩個點提到同一高度,再統一開始跳。

int lca

(int x,int y)

}return f[x][0

];//返回父節點

}

ac**

#include

#include

#include

#include

#include

using namespace std;

int n,m,s,x,y,k,h[

500010

],lg[

500010

],dep[

500010

],f[

500010][

22];struct ca[

1000010];

void

add(int x,int y)

void

dfs(int x,int fa)

int lca

(int x,int y)

}return f[x][0

];}int main()

for(int i=

1;i<=n;i++

) lg[i]

=lg[i-1]

+(1<

==i)

;dfs

(s,0);

for(int i=

1;i<=m;i++

)}

洛谷P3379 模板 最近公共祖先(LCA)

題目描述 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。輸入輸出格式 輸入格式 第一行包含三個正整數n m s,分別表示樹的結點個數 詢問的個數和樹根結點的序號。接下來n 1行每行包含兩個正整數x y,表示x結點和y結點之間有一條直接連線的邊 資料保證可以構成樹 接下來m行每行包含兩...

洛谷 P3379 模板 最近公共祖先(LCA)

如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。輸入格式 第一行包含三個正整數n m s,分別表示樹的結點個數 詢問的個數和樹根結點的序號。接下來n 1行每行包含兩個正整數x y,表示x結點和y結點之間有一條直接連線的邊 資料保證可以構成樹 接下來m行每行包含兩個正整數a b,表示詢問...

洛谷 P3379 最近公共祖先(LCA) 模板

如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。第一行包含三個正整數n m s,分別表示樹的結點個數 詢問的個數和樹根結點的序號。接下來n 1行每行包含兩個正整數x y,表示x結點和y結點之間有一條直接連線的邊 資料保證可以構成樹 接下來m行每行包含兩個正整數a b,表示詢問a結點和b...