LCA 最近公共祖先 筆記 模板

2021-08-15 18:34:42 字數 2614 閱讀 6830

1>dfs遍歷時經過的所有節點的位置

2>每個節點第一次出現的位置

3>每個節點的深度

查詢時先取出兩個節點的位置求出這兩個位置間的深度最小的節點

這個節點就是lca

code:

//by menteur_hxy 2068ms

#include

#include

#include

using

namespace

std;

const

int inf=0x3f3f3f3f;

const

int max=500110;

int n,qu,root,cnt;

int head[max],ver[max*2],first[max],log[max*2],deep[max],f[max*2][21];

struct edgesedge[max*2+5];

void add(int x,int y)

void dfs(int u,int pre)

}}void st()

int k=log[cnt];

for(int j=1;j<=k;j++)

for(int i=1;i+(1

<1

<=cnt;i++)

}int rmq(int l,int r)

int ask(int x,int y)

int main()

cnt=0;

dfs(root,-1);

// for(int i=1;i<=cnt;i++) coutfor(int i=1;i<=qu;i++)

return

0;}

同樣需要dfs,不過只需求出深度和每個節點的父親

現在設f[i][j] 表示i的第2^j個祖先 (eg:f[i][0] 即為i的父親)

所以顯然有 f[i][j]=f[f[i][j-1]][j-1] (i的第2^j-1個祖先的第2^j-1個祖先是i的2^j個祖先)

查詢兩節點時,先將深度較大的節點向上移動直到與另乙個節點深度相同,判斷此時兩節點是否相同如果不同,就從大到小列舉嘗試往上跳直到兩節點父親相同此時父親就是lca

code:

//by menteur_hxy 1860ms

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

const

int max=500010;

int n,qu,root,cnt;

int head[max],deep[max],f[max][20];

/*f[i][j] i的第2^j個祖先

*/struct edgesedge[max*2];

void add(int x,int y)

void dfs_bz(int cur)

}}void init()

int lca_bz(int x,int y)

return f[x][0];

}else

return x;

}int main()

f[root][0]=-1;

dfs_bz(root);

init();

for(int i=1;i<=qu;i++)

return

0;}

先記錄查詢的問題

進行dfs,每次在節點(u)返回前查詢與它構成問題的所有節點(v),如果其中有之前已經遍歷過的節點(vis[v]=true),則這兩個節點的lca為find(v),所有v都查過後,將它與它的父節點的集合合併,之後返回。

code;

//by menteur_hxy 912ms

#include

#include

#include

using

namespace

std;

const

int max=500010;

int n,qu,root,cnt;

int head[max],f[max],head_[max],vis[max],ans[max];

struct edgesedge[max*2],edge_[max*2];

void add(int x,int y)

void add_(int x,int y)

int find(int x)

void tarjan(int u,int pre)

}for(int i=head_[u];i;i=edge_[i].next)

}int main()

f[n]=n;

cnt=0;

for(int i=1;i<=qu;i++)

tarjan(root,-1);

for(int i=1;i<=qu;i++)

printf("%d\n",ans[i]);

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...