//这是刚打的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=500001;
int f[N][20],n,m,s,en,dep[N];
int lg[N],first[N];
struct edge{
int nxt,to;
}ed[N*2];//因为是无向图,还有反向边
int jianbian(int u,int v){
ed[++en].nxt=first[u];
ed[en].to=v;
first[u]=en;
}
void dfs(int now,int fath){
f[now][0]=fath; dep[now]=dep[fath]+1;
for(int i=1; i<=lg[dep[now]]; ++i)//核心
f[now][i] = f[f[now][i-1]][i-1];
for(int i=first[now]; i ; i=ed[i].nxt){
if(ed[i].to!=fath) dfs(ed[i].to,now);
}
}
int LCA(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
while(dep[x] > dep[y])
x=f[x][lg[dep[x]-dep[y]]-1];
if(x==y) return x;
for(int i=lg[dep[x]]-1; i>=0; i--){
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
}
return f[x][0];
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
jianbian(x,y); jianbian(y,x);
}
for(int i=1;i<=n;++i)
lg[i]=lg[i-1]+((1<<lg[i-1]) ==i);
dfs(s,0);
for(int i=1;i<=m;++i){
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",LCA(a,b));
}
return 0;
}
为什么我和原来写的几乎完全一样却全RE呢?
//这是原来的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 500001
using namespace std;
int n,m,s,en;
int first[maxn];
struct edge{
int nxt,e;
}ed[maxn*2];
int fa[maxn][20];//fa[i][j]:i结点向上2^j级祖先
int depth[maxn];//每个结点的深度
int lg[maxn];
void jianbian(int s,int e){
ed[++en].e=e;
ed[en].nxt=first[s];
first[s]=en;
}
/*想要实现这个算法,首先我们要记录各个点的深度和他们2^i级的的祖先,
用数组depth表示每个节点的深度,fa[i][j]表示节点i的2^j级祖先。*/
void dfs(int now,int fath)
{
fa[now][0]=fath; depth[now]=depth[fath]+1;
for(int i=1; i<=lg[depth[now]]; ++i)
fa[now][i] = fa[fa[now][i-1]][i-1];//核心
//意思是now的2^i祖先等于now的2^(i-1)祖先的2^(i-1)祖先
//这里就是倍增的思想
for(int i = first[now]; i ; i = ed[i].nxt)
if(ed[i].e!=fath) dfs(ed[i].e,now);
}
int LCA(int x,int y){
if(depth[x] < depth[y]) swap(x,y);
while(depth[x] > depth[y])
x=fa[x][lg[depth[x]-depth[y]]-1];
if(x==y) return x;
for(int i=lg[depth[x]]-1; i>=0 ; --i)
if(fa[x][i]!=fa[y][i]) //因为我们要跳到它们LCA的下面一层,所以它们肯定不相等,如果不相等就跳过去。
x=fa[x][i],y=fa[y][i];//相等就是过了,要往回收,这次就不加了
return fa[x][0];
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
jianbian(x,y); jianbian(y,x);
}
for(int i=1;i<=n;++i)
lg[i]=lg[i-1]+((1<<lg[i-1]) ==i);
dfs(s,0);
for(int i=1;i<=m;++i){
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",LCA(a,b));
}
return 0;
}