如题,原来听了怎么实现,一直没有写过,然后这是提高里会出现的,于是来补一下(好像我要补的还很多啊^_^)
给大家放一道题:洛谷 P3379 【模板】最近公共祖先(LCA)
温馨提示:这题卡常^_^
代码:(具体看注释)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
inline void read(int &x){//据说这是最快的读入
char ch=' ';
while(!isdigit(ch=getchar()));
x=ch-'0';
while(isdigit(ch=getchar())){
x=x*10+ch-'0';
}
}
int n,m,s;
struct edge{//邻接表存储,卡常用
int to,next;
}e[1000001];//无向图开两倍
//st[k][i]代表从i跳2^k步可以跳到的位置
int st[20][500001],dep[500001],head[500001];//st表,深度,还有邻接表
inline void dfs(int x,int fa,int d){//dfs初始化父亲和深度
st[0][x]=fa;
dep[x]=d;
for(register int i=head[x];i;i=e[i].next){//register卡常,以下省略
if(e[i].to!=fa)dfs(e[i].to,x,d+1);
}
}
void getst(){初始化st表
dfs(s,0,1);//dfs初始化
for(register int k=0;k<19;k++){
for(register int i=1;i<=n;i++){
st[k+1][i]=st[k][st[k][i]];//解释一下这步:先跳2^k步,再跳2^k步,一共就跳了2^(k+1)步
}
}
}
inline int lca(int x,int y){
if(dep[x]>dep[y]){//保证y的深度较大
swap(x,y);
}
for(register int k=19;k>=0;k--){
if(dep[st[k][y]]>=dep[x]){//如果跳不超过,就跳
y=st[k][y];
}
}
if(x==y)return x;
for(register int k=19;k>=0;k--){
if(st[k][x]!=st[k][y]){//如果跳不超过,就跳
x=st[k][x];
y=st[k][y];
}
}
return st[0][x];//这时一定只需要再跳一步了
}
int tot;
inline void addedge(int x,int y){//inline优化
tot++;
e[tot].to=y;
e[tot].next=head[x];
head[x]=tot;
}
int main(){
read(n);
read(m);
read(s);
for(register int i=1;i<=n-1;i++){
int x,y;
read(x);
read(y);
addedge(x,y);
addedge(y,x);
}
getst();
for(register int i=1;i<=m;i++){
int x,y;
read(x);
read(y);
printf("%d
",lca(x,y));
}
return 0;
}