题目链接:祖孙询问
分析
很明显能够想到连边之后一个一个点跳上去看有没有经过目标点。其实就是没有倍增的大暴力LCA。
于是乎就进一步用倍增求LCA模板 。如果x,y的LCA是x,那x是y的祖先,反之亦然。
上代码
赶紧背熟LCA模板!!
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,fa[50001][30],dep[50001];
int tot,hd[100001],rt;
struct node
{
int to,next;
}e[100001];
void add(int x,int y)
{
e[++tot]=(node){y,hd[x]};
hd[x]=tot;
}
void dfs(int x,int fx)
{
fa[x][0]=fx;
dep[x]=dep[fx]+1;
for(int i=1;i<=20;i++)
{
fa[x][i]=fa[fa[x][i-1]][i-1];
/*意思是now的2^i祖先等于now的2^(i-1)祖先的2^(i-1)祖先
2^i=2^(i-1)+2^(i-1)*/
}
for(int i=hd[x];i>0;i=e[i].next)//防止找回他的父亲
{
if(e[i].to!=fx) dfs(e[i].to,x);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=20;i>=0;i--)
{
if(dep[fa[x][i]]>=dep[y])
{
x=fa[x][i];
}
}
if(x==y) return x;
for(int i=20;i>=0;i--)
{
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];//0次方就是直接父亲
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(y!=-1)
{
add(x,y);
add(y,x);
}
else rt=x;
}
dfs(rt,0);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
//cout<<lca(x,y)<<" "<<lca(y,x)<<endl;
if(lca(x,y)==y) printf("2\n");
else if(lca(x,y)==x) printf("1\n");
else printf("0\n");
}
return 0;
}