原來學習最小生成樹的時候寫了道題,發現得用最近公共祖先迫於無奈便學了lca(不過確實很有用)
lca主要基於一種倍增的思想,和st表很像,通過預處理資料來花費空間換取時間。
要想學習怎麼求lca首先要學習lca是什麼。
在一顆數中,比如說圖中的4和5,那麼他們的最近公共祖先便是2。
如果是2和3他們的最近公共祖先便是1,而2和4的最近公共祖先是2本身,所以最近公共祖先也可以是自己。
那麼要如何來求呢。最樸素的做法是用dfs進行搜尋查詢,但這樣的時間複雜度太高了。
於是就出現了這種基於倍增的lca。
這裡盜用一張洛谷的圖,上面那圖太小了
------------恢復內容開始------------
原來學習最小生成樹的時候寫了道題,發現得用最近公共祖先迫於無奈便學了lca(不過確實很有用)
lca主要基於一種倍增的思想,和st表很像,通過預處理資料來花費空間換取時間。
要想學習怎麼求lca首先要學習lca是什麼。
在一顆數中,比如說圖中的4和5,那麼他們的最近公共祖先便是2。
如果是2和3他們的最近公共祖先便是1,而2和4的最近公共祖先是2本身,所以最近公共祖先也可以是自己。
那麼要如何來求呢。最樸素的做法是用dfs進行搜尋查詢,但這樣的時間複雜度太高了。
於是就出現了這種基於倍增的lca。
這裡盜用一張洛谷的圖,上面那圖太小了
比如說我們想求17和8的公共祖先,我們便要考慮將17和8給弄到同一層(即樹的深度,第一層的深度是1)
17比8的深度要深,所以得先把17往上面爬。
如果一層一層的爬,那效率便太低了,所以我們便考慮一此直接爬2^n層。
比如這裡17爬到10,我們直接爬2^1層,便不用爬兩次了。
爬到相同的層數之後,我們還要繼續爬,不過這時是兩邊一起爬相同的層數,也是一次爬2^n層,一直到爬到相同的節點便ok了,這時的這個節點便是我們要找的最近公共祖先。
講了那麼多現在最重要的便是如何實現了。
話不多說先上**再講解(這裡是資料的預處理階段採用dfs)
void dfs(int here,int這步預處理是演算法的核心,而這步的核心便是對二維陣列f[i][j]的操作fa)
這個陣列中儲存的數代表著i這個節點往上跳2^j步所到的節點。
預處理完了便是查詢了。
int lca(int x,int這樣lca大概就講完了,最後附上全部**y) }//讓x和y一同往上跳,如過跳到下一層他們就相同就不跳了
return f[x][0
];因為下一層才相同,所以return x往上跳2^0層
}
#include#include**比較醜,多多包含#include
#include
#include
#define maxx 1000005
using
namespace
std;
int head[maxx], now = 0, n, m, lg[maxx], f[maxx][32
], depth[maxx], vis[maxx], p;
struct
edge a[maxx*2
];void add_edge(int at, int
to)
void swap(int& x, int&y)
void dfs(int here,int
fa)
for (int i = head[here]; i; i =a[i].nex)
if(!vis[a[i].to])
dfs(a[i].to, here);
}int lca(int x,int
y) }
return f[x][0];}
intmain()
lg[0] = -1
;
for (int i = 1; i <= n; i++)
dfs(p, 0);
for (int i = 1; i <= m; i++)
return0;
}
最近公共祖先 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,表示詢問...
LCA 最近公共祖先
定義 對於有根樹t的兩個結點u v,最近公共祖先lca t,u,v 表示乙個結點x,滿足x是u v的祖先且x的深度盡可能大。另一種理解方式是把t理解為乙個無向無環圖,而lca t,u,v 即u到v的最短路上深度最小的點。現在給定乙個根為1的樹,求某兩個點的最近公共祖先。思路 預處理出每個點的深度再一...