acwing-1172. 祖孙询问(最近公共祖先)「建议收藏」

acwing-1172. 祖孙询问(最近公共祖先)「建议收藏」给定一棵包含 n 个节点的有根无向树 节点编号互不相同 但不一定是 1 n 有 m 个询问 每个询问给出了一对节点的编号 x 和 y 询问 x 与 y 的祖孙关系 输入格式 输入第一行包括一个整数 表示节点个数 接下来 n 行每行一对整数 a 和 b 表示 a 和 b 之间有一条无向边 如果 b 是 1 那么 a 就是树的根 第 n 2 行是一个整数 m 表示询问个数 接下来 m

给定一棵包含 n 个节点的有根无向树,节点编号互不相同,但不一定是 1∼n。

有 m 个询问,每个询问给出了一对节点的编号 x 和 y,询问 x 与 y 的祖孙关系。

输入格式
输入第一行包括一个整数 表示节点个数;

接下来 n 行每行一对整数 a 和 b,表示 a 和 b 之间有一条无向边。如果 b 是 −1,那么 a 就是树的根;

第 n+2 行是一个整数 m 表示询问个数;

接下来 m 行,每行两个不同的正整数 x 和 y,表示一个询问。

输出格式
对于每一个询问,若 x 是 y 的祖先则输出 1,若 y 是 x 的祖先则输出 2,否则输出 0。

数据范围
1≤n,m≤4×104,
1≤每个节点的编号≤4×104
输入样例:

10
234 -1
12 234
13 234
14 234
15 234
16 234
17 234
18 234
19 234
233 19
5
234 233
233 12
233 13
233 15
233 19

输出样例:

1
0
0
0
2

题解
倍增法求LCA

#include
#define x first
#define y second
#define send string::npos
#define lowbit(x) (x&(-x))
#define left(x) x<<1
#define right(x) x<<1|1
using namespace std;
typedef long long ll;
typedef pair PII;
typedef struct Node * pnode;
const int N = 2e5 + 10;
const int M = 3 * N;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int Mod = 1e9;
int n,m;
int fa[N][16],depth[N];
int q[N],hh = 0,tt = 0;
int head[N],cnt;
struct Edge{

int v,next;
}edge[M];
void add(int u,int v){

edge[cnt].v = v;
edge[cnt].next = head[u];
head[u] = cnt ++;
}
void bfs(int root){
//预处理
memset(depth,INF,sizeof depth);
q[0] = root;
depth[0] = 0;
depth[root] = 1,fa[root][0] = 0;
while(hh <= tt){

int t = q[hh ++];
for(int i = head[t];~i;i = edge[i].next){

int ver = edge[i].v;
if(depth[ver] < depth[t] + 1)continue;
depth[ver] = depth[t] + 1;
q[++ tt] = ver;
fa[ver][0] = t;
for(int k = 1;k < 16;k ++){

fa[ver][k] = fa[fa[ver][k - 1]][k - 1];
}
}
}
}
int lca(int a,int b){

if(depth[a] < depth[b])swap(a,b);
for(int k = 15;k >= 0;k --)
if(depth[fa[a][k]] >= depth[b])
a = fa[a][k];
if(a == b)return a;
for(int k = 15;k >= 0;k --)
if(fa[a][k] != fa[b][k]){

a = fa[a][k];
b = fa[b][k];
}
return fa[a][0];
}
int main(){

memset(head,-1,sizeof head);
int n,x,y,root;
cin>>n;
for(int i = 0;i < n;i ++){

cin>>x>>y;
if(y == -1)root = x;
else{

add(x,y);
add(y,x);
}
}
int m,a,b;
cin>>m;
bfs(root);
for(int i = 0;i < m;i ++){

cin>>a>>b;
int res = lca(a,b);
if(res == a)cout<<1< else if(res == b)cout<<2< else cout<<0< }
return 0;
}
编程小号
上一篇 2025-02-09 15:17
下一篇 2025-10-07 12:46

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/hz/133031.html