LCA 倍增
#include<iostream>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 10086;
int num[maxn];
int bin[30];
int deep[maxn];
int q1,q2;
int fa[maxn][30];
vector<int>u[maxn];
int root;
void get_f()
{
for(int i=0;i<=20;i++){
bin[i]=(1<<i);
}
}
void build()//输入,建树,并找到根节点
{
int n;
int x,y;
scanf("%d",&n);
for(int i=1;i<=n-1;i++){
scanf("%d%d",&x,&y);
u[x].push_back(y);
num[y]++;
}
for(int i=1;i<=n;i++){
if(!num[i]){
root=i;
}
}
scanf("%d%d",&q1,&q2);
}
void init()//初始化
{
memset(fa,0,sizeof(fa));
memset(deep,0,sizeof(deep));
memset(num,0,sizeof(num));
for(int i=0;i<maxn;i++){
u[i].clear();
}
}
void bfs()//找出每个节点的深度,填写fa数组
{
queue<int>q;
int cur;
q.push(root);
deep[root]=1;
while(!q.empty()){
cur=q.front();q.pop();
for(int i=1;i<20;i++){
if(deep[cur]<bin[i]){break;}
fa[cur][i]=fa[fa[cur][i-1]][i-1];//现在这个节点的第2^i个爸爸
//就是他的2^(i-1)个爸爸的第2^(i-1)个爸爸
}
int siz=u[cur].size();
for(int i=0;i<siz;i++){
q.push(u[cur][i]);
fa[u[cur][i]][0]=cur;//亲爸爸
deep[u[cur][i]]=deep[cur]+1;
}
}
}
int lca()
{
int x=q1,y=q2;
if(deep[x]<deep[y]){swap(x,y);}
int t=deep[x]-deep[y];
for(int i=0;i<20;i++){
if(t&bin[i]){x=fa[x][i];}
}//化为相同深度
for(int i=19;i>=0;i--){
if(fa[x][i]^fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}//如果第2^i个父节点不同,一同向上移动
if(x==y){return x;}
return fa[x][0];
}
int main()
{
int T;
get_f();
scanf("%d",&T);
while(T--){
init();
build();
bfs();
printf("%d\n",lca());
}
return 0;
}
代码可以AC POJ1330
如需转载,请注明出处
如有侵权,联系删除
2290713181@qq.com
如有侵权,联系删除
2290713181@qq.com

浙公网安备 33010602011771号