《學習筆記》 倍增 lca

2022-08-13 22:24:19 字數 2035 閱讀 3614

例題:codevs 2370 小機房的樹

簡單來說就是給你乙個n個點的樹,每一條邊都有邊權。詢問有m次,每次給出兩個點,求他們之間的最小邊權和。

很容易想到用求樹上字首和和lca,先把兩個點跳到高度相同的地方,再一直往上跳,直到兩個點重合。因為乙個點乙個點的跳太慢了,所以我們倍增的跳來求lca。

令f[i][j]表示i號點往上跳2^j步的父親。

則 f[i][j]=f[f[i][j-1]][j-1];

這裡有兩個板子,思想都一樣。

板子一

1 #include2 #include3 #include4 #include5 #include6

using

namespace

std;78

intn,m,u,v,c,cnt;

9int sum[50010],deep[50010],fa[50010][30],first[50010],next[100020

];10

struct

maplerode[100020

];13

14void build(int f,int t,int d) //

注意雙向建邊15;

17 next[cnt]=first[f];

18 first[f]=cnt;19}

20void dfs(int f,int t,int d) //

dfs處理出樹

2129

void done() //

預處理倍增跳的fa

3035

int lca(int x,int

y)36

43if(x==y) return

x;44

for(int i=log2(n);i>=0;--i) //

一起往上跳

45if(fa[x][i]!=fa[y][i])

46 x=fa[x][i],y=fa[y][i];

47return fa[x][0

];48}49

intmain()

5058 dfs(0,0,0

);59

done();

60 scanf("

%d",&m);

61while(m--)

6266

return0;

67 }

板子二

1 #include2 #include3 #include4 #include5 #include6

using

namespace

std;78

intn,u,v,c,m;

9int first[150010],next[150010],fa[150010][30],deep[150010

],cnt;

10int de[60000

];11

struct

maplerode[150010

];14

15void done(int f,int t,int

v)16

26void build(int f,int t,int

d)27

;29 next[cnt]=first[f];

30 first[f]=cnt; 31}

32int lca(int x,int

y)33

42if(x==y) return

x;43

for(int i=log2(n);i>=0;--i)

44if(fa[x][i]!=fa[y][i])

45 x=fa[x][i],y=fa[y][i];

46return fa[x][0

];47}48

49int

main()

5060 done(0,0,0

);61 scanf("

%d",&m);

62while(m--)

6367

return0;

68 }

學習筆記 lca 倍增

求一棵樹上兩個節點的最近公共祖先有兩種演算法 tarjan 離線 這篇博文只介紹倍增的寫法.f i j 表示節點 i 的祖先中,與節點 i 距離為 2 j 的節點編號.那麼 f i j beginroot i root father i j 0,i not root f i j f f i j 1 ...

LCA 倍增 學習小結

lca問題,即lowest common ancestor 最近公共祖先 lca問題有很多解法,比如 暴力解法 分塊解法 倍增演算法 tarjan演算法 lct演算法 在這裡呢,我們只討論倍增 倍增演算法其實是一種類似於dp的實現 pa i j p a i j 表示i號節點的2j 2 j個父親 pa...

倍增LCA複習

時間過去了如此之久,我連倍增lca都不怎麼記得了,要粗事啊。首先預處理層數和每個節點的父親,然後預處理p陣列,p i,j 表示i向上第2 j個祖先。最後對於每個詢問x,y先把x,y變成同一層數的 x或y向上走直到兩個層數相等 然後x,y同時向上走,直到x和y的父親相同位置。自 1.dfs預處理出所有...