樹,LCA,最近公共祖先,倍增

2022-07-26 14:09:16 字數 1936 閱讀 1698

最近公共祖先,

樹上倍增,lca,

fa [ i ] [ j ] 表示 i 節點向上 2j 的祖先

很像dp,

k 屬於 [ 1 , log ( n ) ] ,f [ x ][ k ] = f [ f [ x ] [ k-1 ]] [k-1]

算lca時,

先不妨設 d [ x ] >= d [ y ]

二進位制拆分

嘗試從x 向上走 k = 2log (n),~~,21,20,

檢查到的點是否比 y 深

每次檢查中,若是,x= f [ x ] [ k ]

若仍未相會, 即 f [ x ] [ k ] != f [ y ] [ k ]

令 x = f [ x ] [ k ], y = f [ y ] [ k ]

最後,若 x = y , lca ( x , y )=y

看看**

#include #include 

#include

#include

using

namespace

std;

#define maxn 50010

int fa[maxn][20

];//

f[i][j]表示i的2^j的祖先

int dep[maxn];//

深度int dis[maxn];//

到根節點距離

struct

edge e[maxn*2

];int

head[maxn];

intt,n,m,cnt;

int t;//

指數次冪 t=(log(n)/log(2))+1

void add(int x,int y,int

z) queue

q;void

bfs()

q.push(y);}}

}int lca(int x,int

y) }

if (x==y) return

x;

for (int i=t; i>=0; i--)

}return fa[y][0];}

intmain ()

bfs();

/*for (int i=1; i<=n; i++)

return0;

}/*10 5

1 2 2

1 3 4

2 4 3

2 5 7

3 6 2

3 7 4

4 8 2

5 9 3

6 10 1

6 79 3

8 510 6

4 7*/

還有一種:

#include

#include

#include

using

namespace

std;

intn,q,cnt;

int deep[1001],head[1001],dis[1001],fa[1001][11

];bool vis[1001

];struct datae[2001

];void ins(int u,int v,int

w)void insert(int u,int v,int

w)void dfs(int

x)

for(int i=head[x];i;i=e[i].next)

}int lca(int x,int

y)

if(x==y)return

x;

else

return fa[x][0];}

intmain()

dfs(1);

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

return0;

}

ok啦

LCA 最近公共祖先 (倍增演算法)

首先了解一下我們 最近公共祖先 e和g的lca為a l和j的lca為d k和f的lca為b 然後 倍增 用到了二進位制和 dp 的思想 倍增 就是 1 2 4 8 16 任何乙個數 都是可以右 這些數相加得到的。了解一下二進位制 首先 定義 fa i j 為 從 i 節點 向上走 2 j 個節點,d...

最近公共祖先 LCA 倍增演算法

樹上倍增求lca lca指的是最近公共祖先 least common ancestors 如下圖所示 4和5的lca就是2 那怎麼求呢?最粗暴的方法就是先dfs一次,處理出每個點的深度 然後把深度更深的那乙個點 4 乙個點地乙個點地往上跳,直到到某個點 3 和另外那個點 5 的深度一樣 然後兩個點一...

樹上倍增求LCA(最近公共祖先)

前幾天做faebdc學長出的模擬題,第三題最後要倍增來優化,在學長的講解下,嘗試的學習和編了一下倍增求lca 我能說我其他方法也大會嗎?倍增求lca father i j 表示節點i往上跳2 j次後的節點 可以轉移為 father i j father father i j 1 j 1 此處注意迴圈...