LCA

21 篇文章 0 订阅
2 篇文章 0 订阅
表示上lca那节课我没去,所以程序什么的可能变得有漏洞或者是不标准。

#include<iostream>
#include <fstream>
#include <cmath>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
#define cin fin
#define cout fout
int n;
struct Tnode
{
int h,left,right,fa;
int pos;
int table[50];
};
Tnode tree[100001];
int root,ask;
int bfs[100001];
int Max=0;

int lca(int x,int y)
{
Tnode a=tree[x],b=tree[y];
if(a.h<b.h)
{
Tnode temp=a;
a=b;
b=temp;
}
int temp=a.h-b.h;
while(temp!=0)
{
int t=temp&(-temp);
a=tree[a.table[int(log2(t))]];
temp-=t;
}
int d=40;
int ta=0,tb=0;
bool f;
if(a.pos==b.pos)
return a.pos;
while(d>=0)
{
ta=a.table[d],tb=b.table[d];
if(ta==0 || tb==0)
{
d--;
continue;
}
// cout<<ta<<" "<<tb<<" "<<d<<endl;
if(ta==tb)
f=1;
else f=0;
if(!f) a=tree[ta],b=tree[tb];
d--;
}
return ta;
}

void makeT(int num,int l)
{
if(l>Max*2) return ;
for(int i=1;i<=n;i++)
tree[i].table[num]=tree[tree[i].table[num-1]].table[num-1];
// cout<<tree[i].table[num]<<" ";
// cout<<num<<endl;
makeT(num+1,l*2);
}

int main()
{
cin>>n;
cin>>root>>ask;
int x,y;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
tree[i].left=x;
tree[i].right=y;
tree[x].fa=i;
tree[y].fa=i;
tree[i].pos=i;
}
for(int i=1;i<=n;i++)
tree[i].table[0]=tree[i].fa;
int head=0,last=0;
bfs[0]=root;
tree[root].h=1;
for(;head<=last;head++)
{
if(tree[bfs[head]].left!=0)
{
last++;
bfs[last]=tree[bfs[head]].left;
tree[bfs[last]].h=tree[bfs[head]].h+1;
}
if(tree[bfs[head]].right!=0)
{
last++;
bfs[last]=tree[bfs[head]].right;
tree[bfs[last]].h=tree[bfs[head]].h+1;
}
}

for(int i=1;i<=n;i++)
Max=max(Max,tree[i].h);
makeT(1,2);
for(int i=0;i<ask;i++)
{
cin>>x>>y;
cout<<lca(x,y)<<endl;
}


return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值