最近公共祖先,
樹上倍增,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 此處注意迴圈...