模板 最近公共祖先 LCA

2022-09-03 06:06:09 字數 1807 閱讀 7805

給出乙個樹和m

m組詢問,對於每個詢問輸出兩個結點的lca

lca。

##思路:

思路一:樹上倍增

樹上倍增是lca

lca的基本方法之一。其做法是先將xx和y

y跳到統一深度上,再利用倍增思想找到兩點的lca

lca。

所以要先用dfs

dfs求出每個點的深度以及它的祖宗,然後在對於每一詢問完成上述操作即可。

思路二:sts

t表對於一棵樹上的兩個不同節點xx和y

y,從根開始跑一遍尤拉序,設x

x在尤拉序中第一次出現的位置為fir

st[x

]fir

st[x

],yy第一出現的位置是fir

st[y

]fir

st[y

],那麼xx和y

y的lca

lca就是尤拉序中fir

st[x

]fir

st[x

]到fir

st[y

]fir

st[y

]之間深度最低的(即min

(dep

[i])

min(

dep[

i]))節點就是它們的lca

lca。

證明略。但是很明顯是正確的。

所以,先跑一邊dfs

dfs求出fir

st[i

]fir

st[i

]和尤拉序,再利用sts

t表求出任意區間的最小值(lca

lca),然後再讀入輸出即可。

注意!此方法時間較慢,需要輸入輸出流才能過!

##**:

樹上倍增:

#include #include #include #include #define n 500030

#define lg 25

using namespace std;

int dep[n+1],head[n+1],lg[lg+1],k,n,m,s,x,y,f[n+1][lg+1];

struct edge //鄰接表

e[n<<1+1];

void add(int from,int to)

void dfs(int x,int fa) //求每個點的深度

return f[x][0];

}int main()

return 0;

}

sts

t表:

#include #include #include #include #define n 500020

#define lg 20

using namespace std;

int first[n<<1+1],dep[n<<1+1],vis[n<<1+1],rmq[n<<1+1][lg],num[n<<1+1][lg],head[n<<1/+1];

int n,m,s,k,sum,x,y,z;

struct edge

e[n<<1+1];

int f;

char c;

int read() //輸入流

void write(int x) //輸出流(可以不用)

void add(int from,int to)

void dfs(int x,int k) //求尤拉序

return;

}int main()

getchar();getchar();

return 0;

}

模板 最近公共祖先(LCA)

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

模板 lca 最近公共祖先

lca hljs cpp include include using namespace std const int maxn 500001 int n,m,gen,x,y struct edgeedge 2 maxn int deep maxn fa maxn 20 deep記錄每個點的深度,fa...

最近公共祖先 LCA 模板

lca即最近公共祖先,是指 在有根樹中,找出某兩個結點u和v最近的公共祖先。時間複雜度o nlogn m n 步驟 1.將樹看作乙個無向圖,從根節點開始深搜,得到乙個遍歷序列。2.在x y區間中利用rmq演算法找到深度最小返回其下標。可以上洛谷找模板題測試 include include inclu...