- 【时光蒸汽喵带你做专题】最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
- tarjan LCA - YouTube
- Tarjan算法_LCA - A_Bo的博客 - CSDN博客
- Tarjan离线算法求最近公共祖先(LCA) - 初学者 - CSDN博客
- 最近公共祖先(LCA) - riteme.site
- Fuzhou University OnlineJudge 1628
- P3379 【模板】最近公共祖先(LCA) - 洛谷 | 计算机科学教育新生态
- 有向图强连通分量的Tarjan算法 - BYVoid
- Tarjan算法 详解+心得 - Christopher_Yan - 博客园
- UESTCACM 每周算法讲堂第25期 Tarjan求强连通分量_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
洛谷P3379 【模板】最近公共祖先(LCA)
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include <set>
#include <stack>
#include <map>
#include<vector>
using namespace std;
const int maxn = 5e5 + 5;
struct query
{
int x;
int y;
int lca;
}query[maxn];
int fa[maxn];
bool vis[maxn];
int deep[maxn];
vector<int> G[maxn];
vector<int> Q[maxn];
void init()
{
for (int i = 0; i < maxn; i++)
{
fa[i] = i;
}
}
int find(int x)
{
if (fa[x] == x)
return x;
else
return fa[x] = find(fa[x]);
}
void Union(int v, int u)
{
int vfa = find(v), ufa = find(u);
if (vfa == ufa)return;
else fa[v] = u;
}
void tarjan(int u)
{
vis[u] = true;
for (auto qid : Q[u]) {
if (query[qid].x == u) {
if (vis[query[qid].y]) {
query[qid].lca = find(query[qid].y);
}
}
else
{
if (vis[query[qid].x]) {
query[qid].lca = find(query[qid].x);
}
}
}
for (auto v : G[u]) {
if (vis[v])
continue;
deep[v] = deep[u] + 1;
tarjan(v);
Union(v, u);
}
}
int main()
{
init();
int n, m, s;
scanf_s("%d%d%d", &n, &m, &s);
int x, y;
for (int i = 1; i < n; i++)
{
scanf_s("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
for (int i = 1; i <= m; i++)
{
scanf_s("%d%d", &query[i].x, &query[i].y);
Q[query[i].x].push_back(i); // 对于节点 x 来说有一个编号为 i 的询问
Q[query[i].y].push_back(i);
}
tarjan(s);
for (int i = 1; i <= m; i++)
{
printf("%d
", query[i].lca);
}
for (int i = 1; i <= n; i++)
{
printf("节点 %d 的深度是 %d
", i, deep[i]);
}
}
FOJ 1628 计算公共祖先的个数
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include <set>
#include <stack>
#include <map>
#include<vector>
using namespace std;
const int maxn = 5e5 + 5;
struct query
{
int x;
int y;
int lca;
}query[maxn];
int fa[maxn];
bool vis[maxn];
int deep[maxn];
vector<int> G[maxn];
vector<int> Q[maxn];
void init()
{
deep[1] = 1;
for (int i = 0; i < maxn; i++)
{
fa[i] = i;
}
}
int find(int x)
{
if (fa[x] == x)
return x;
else
return fa[x] = find(fa[x]);
}
void Union(int v, int u)
{
int vfa = find(v), ufa = find(u);
if (vfa == ufa)return;
else fa[v] = u;
}
void tarjan(int u)
{
for (int i = 0; i < Q[u].size(); i++) {
if (query[Q[u][i]].x == u) {
if (vis[query[Q[u][i]].y]) {
query[Q[u][i]].lca = find(query[Q[u][i]].y);
}
}
else
{
if (vis[query[Q[u][i]].x]) {
query[Q[u][i]].lca = find(query[Q[u][i]].x);
}
}
}
vis[u] = true;
for (int i = 0; i < G[u].size(); i++) {
if (vis[G[u][i]])
continue;
deep[G[u][i]] = deep[u] + 1;
tarjan(G[u][i]);
Union(G[u][i], u);
}
}
int main()
{
init();
int n, k, m;
int x, y;
scanf_s("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf_s("%d", &k);
for (int j = 1; j <= k; j++)
{
scanf_s("%d", &y);
G[i].push_back(y);
G[y].push_back(i);
}
}
scanf_s("%d", &m);
for (int i = 1; i <= m; i++) // 离线处理
{
scanf_s("%d%d", &query[i].x, &query[i].y);
Q[query[i].x].push_back(i); // 对于节点 x 来说有一个编号为 i 的询问
Q[query[i].y].push_back(i);
}
tarjan(1);
/*for (int i = 1; i <= m; i++)
{
printf("%d
", query[i].lca);
}
for (int i = 1; i <= n; i++)
{
printf("节点 %d 的深度是 %d
", i, deep[i]);
}*/
for (int i = 1; i <= m; i++)
{
printf("%d
", deep[query[i].lca]);
}
}