LCA演算法實現

2022-05-19 21:22:00 字數 1837 閱讀 5701

參考問題:洛谷p3379 【模板】最近公共祖先(lca):

暴力解法,dfs一下,求得所有點的深度,然後每當我們要求 \(x\) 和 \(y\) 的 lca 的時候,我們就迴圈的去判斷:

這種暴力的解法的時間複雜度達到了 \(o(n \cdot m)\),實現**如下:

#include using namespace std;

const int maxn = 500050;

int n, m, rt, pa[maxn], dep[maxn];

vectorg[maxn];

void dfs(int u, int d)

}int query(int x, int y)

return x;

}int main()

dfs(rt, 1);

while (m --)

return 0;

}

借助於倍增思想可以將上述演算法優化到 \(o(m \cdot log n)\),

下面的實現中:

\(pa[u][i]\) 表示深度比 \(u\) 小 \(2^i\) 的祖先節點的編號,如果這個節點不存在,則該值對應為 \(rt\)(根節點)。

實現**如下:

#include using namespace std;

const int maxn = 500050;

int n, m, rt, pa[maxn][21], dep[maxn];

vectorg[maxn];

void dfs(int u, int p)

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

}return pa[x][0];

}int main()

dfs(rt, 0);

while (m --)

return 0;

}

然而不知為何在這道題仍然是70分超時。(可能是由於對數影響)

參考資料:

注:寫的非常好。

實現**如下:

#include using namespace std;

const int maxn = 500050, maxm = maxn*2;

struct edge ;

edge(int _v, int _nxt)

} edge[maxm];

int n, m, rt, head[maxn], ecnt;

int f[maxn];

void init()

void addedge(int u, int v)

struct query ;

query(int _id, int _v)

};vectorquery[maxn];

void addquery(int x, int y, int id)

int find(int x)

void union(int x, int y)

int vis[maxn], ans[maxn];

void tarjan(int u)

int sz = query[u].size();

for (int i = 0; i < sz; i ++)

vis[u] = 2;

}int main()

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

tarjan(rt);

for (int i = 1; i <= n; i ++) printf("%d\n", ans[i]);

return 0;

}

LCA演算法模板

include include include include define ll long long using namespace std lac演算法模板 題目 poj how far way 複雜度 n k k 次詢問 雙鏈式前向星 乙個建圖 乙個回答 int n m const int m...

LCA倍增演算法

一.倍增演算法的前期鋪墊 我們記節點v到根的深度為depth v 那麼如果節點w是節點u和節點v的最近公共祖先的話,讓u往上走 depth u depth w 步,讓v往上走 depth v depth w 步,都將走到節點w。因此,我們首先讓u和v中較深的乙個往上走 depth u depth v...

LCA離線演算法tarjan

lca演算法 lca least common ancestor 是指在一棵樹中,距離兩個點最近的兩者的公共節點。也就是說,在兩個點通往根的道路上,肯定會有公共的節點,我們就是要求找到公共的節點中,深度盡量深的點。還可以表示成另一種說法,就是如果把樹看成是乙個圖,這找到這兩個點中的最短距離。本文先介...