參考問題:洛谷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 是指在一棵樹中,距離兩個點最近的兩者的公共節點。也就是說,在兩個點通往根的道路上,肯定會有公共的節點,我們就是要求找到公共的節點中,深度盡量深的點。還可以表示成另一種說法,就是如果把樹看成是乙個圖,這找到這兩個點中的最短距離。本文先介...