樹上倍增法求LCA

2021-09-28 14:27:21 字數 1272 閱讀 1359

我們找的是任意兩個結點的最近公共祖先, 那麼我們可以考慮這麼兩種種情況:

1.兩結點的深度相同.

2.兩結點深度不同.

第一步都要轉化為情況1,這種可處理的情況。

先不考慮其他, 我們思考這麼乙個問題: 對於兩個深度不同的結點, 把深度更深的那個向其父節點迭代, 直到這個迭代結點和另乙個結點深度相同, 那麼這兩個深度相同的結點的lca也就是原兩個結點的lca. 因此第二種情況轉化成第一種情況來求解lca是可行的. 這裡我們使用倍增法以最快的速度找到相同的深度,然後開始求lca。求lca使用倍增法,倍增的條件是找到相同的祖先,減小步距。

/*

*/const int maxn = 10010;

const int deg = 20;

struct edge

edge[maxn * 2];

int head[maxn], tot;

void addedge(int u, int v)

void init()

int fa[maxn][deg]; // fa[i][j]表示結點i的第2^j個祖先

int deg[maxn]; // 深度陣列

void bfs(int root)

for (int i = head[tmp]; i != -1; i = edge[i].next)

deg[v] = deg[tmp] + 1;

fa[v][0] = tmp;

que.push(v);}}

}int lca(int u, int v)

int hu = deg[u], hv = deg[v];

int tu = u, tv = v;

for (int det = hv-hu, i = 0; det ; det >>= 1, i++)

}if (tu == tv)

for (int i = deg - 1; i >= 0; i--)

tu = fa[tu][i];

tv = fa[tv][i];

}return fa[tu][0];

}bool flag[maxn];

int main()

int root;

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

}bfs(root);

scanf("%d%d", &u, &v);

printf("%d\n", lca(u, v));

}return 0;

}

12 16 樹上倍增法求LCA

1.預處理 節點的深度d 到根節點的距離dist 該點向上走2 k步能夠到達的點 f陣列。2.lca 將兩個節點調整到同乙個深度,只調整深的那個即可。如果 結束後,這兩個點重合,說明該點就是所求的點。否則,從大往小開始試跳躍的步數,直至將這兩個點調整為目標點的兩個子節點。最後兩點的父節點就是所求的l...

演算法 樹上倍增求LCA

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

倍增法求 LCA

預處理 通過dfs遍歷,記錄每個節點到根節點的距離dist u 深度d u 並求出樹上每個節點i的2 j祖先f i j 求最近公共祖先,根據兩個節點的的深度,如不同,向上調整深度大的節點,使得兩個節點在同一層上,如果正好是祖先結束,否則,將連個節點同時上移,查詢最近公共祖先。include incl...