- 【模板】最近公共祖先(LCA)
可以帮我看一下哪错了吗
- 2025-3-30 10:02:53 @
using namespace std;
const int N = 1e4+10;
int n, q, x, y, father[N][25], dep[N];
vector<int>g[N];// 方便深搜遍历
void dfs(int x){
if(father[x][0] == 0){
dep[x] = 1;
}
else {
dep[x] = dep[father[x][0]]+1;
}
for(int i = 0;i<g[x].size();i++){
int v = g[x][i];//x 能到达的点
if(v!= father[x][0]){
dfs(v);
}
}
}
int LCA(int x, int y){
//调平
if(dep[x]<dep[y]){//保证x较深
swap(x, y);
}
int k = 0;
for(int i = 15;i>=0;i--){
if(dep[father[x][i]]>=dep[y]){
x = father[x][i];
}
}
if(x == y) return x;
//一起往上跳
for(int i = 15;i>=0;i--){
if(father[x][i] != father[y][i]){
x = father[x][i];
y = father[y][i];
}
}
return father[x][0];
}
int main(){
scanf("%d", &n);
for(int i = 1;i<n;i++){
scanf("%d %d", &x, &y);//输入边
g[x].push_back(y);
father[y][0] = x;
}
//找一下根
int root;
for(int i = 1;i<=n;i++){
if(father[i] == 0){
root = i;
break;
}
}
dfs(root);//统计每个点的深度
// 处理st表
for(int j = 1;(1<<j)<=n;j++){
for(int i =1;i<=n;i++){
father[i][j] = father[father[i][j-1]][j-1];
}
}
scanf("%d", &q);
while(q--){
scanf("%d %d",&x, &y);
printf("%d\n", LCA(x, y));
}
return 0;
}
1 条评论
-
-
//蒟蒻 //#pragma GCC optimize(2) #include<bits/stdc++.h> using namespace std; const int N = 10010; int n, q, a, b, father[N][25], dep[N]; vector<int> g[N]; //邻接链表 void dfs (int u) { // 统计深度 if( father [u][0] == 0 ) dep[u] = 1; else dep[u] = dep[father[u][0]] + 1; for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if ( v != father[u][0] ) dfs(v); //不走回头路 } } int LCA(int x, int y){ //调平? if(dep[x] < dep[y]) swap(x, y); for(int i = 15; i >= 0; i--){ if(dep[father[x][i]] >= dep[y]) x = father[x][i]; if(x == y) return x; // 一起上浮 for(int i = 15; i >= 0; i--){ if(father[x][i] != father[y][i]){ x = father[x][i]; y = father[y][i]; } } } // 再向上一步 return father[x][0]; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); scanf ( "%d", &n ); for (int i = 1; i < n; i++) { scanf ( "%d %d", &a, &b ); g[a].push_back(b); father[b][0] = a; } //找一下根 int root; for(int i = 1; i<= n; i++) { if(father[i][0] == 0) { root = i; break; } } dfs(root); //处理st表 for (int j = 1; (1 << j) <= n; j++) { for (int i = 1; i <= n; i++) { // 枚举起点 father [i][j] = father[father[i][j-1]][j-1]; } } scanf("%d", &q); while(q--){ scanf("%d %d", &a, &b); printf("%d\n",LCA(a, b)); } return 0; }
- 1
信息
- ID
- 1376
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 148
- 已通过
- 32
- 上传者