您的位置:首页 > 其它

LCA(最近公共祖先)倍增法模板及总结

2017-04-03 10:41 393 查看
还是markdown编辑器好啊

写lca写了一段时间 有ST表的在线查询方法但是我一直没写AC过。。。。所以先把倍增的丢这里好了

复杂度O(nlogn) ,n是dfs用的 logn是倍增往上跳用的。。。。然后大致的思路就是 在dfs时记每个点的深度 求2点lca时先将两点跳到同一深度 再一起跳到同一点 至于每个这样的距
4000
离一定会由2的整次幂组成 所以一定会在最后跳到lca下一层的位置。

好吧也许你不知道我在说什么 看代码你也许就懂了

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;

const int maxn=500000+50;
const int maxm=500000+50;
const int max_log_n=20;
int n,m,s;
struct edge
{
int to,next;
};
edge es[maxn<<1];
int head[maxn];
int pa[20][maxn];
int depth[maxn];
int cnt=0;
void addedge(int from,int to)
{
es[cnt].to=to;
es[cnt].next=head[from];
head[from]=cnt++;
}

void dfs(int v,int fa)
{
pa[0][v]=fa;
if(v!=s) depth[v]=depth[fa]+1;
else depth[v]=1;
int k=1;
if(pa[k-1][v]!=-1)
{
while(pa[k-1][pa[k-1][v]]!=-1)
{
pa[k][v]=pa[k-1][pa[k-1][v]];
k++;
}
}
for(int j=head[v];j>=0;j=es[j].next)
{
int u=es[j].to;
if(u!=fa)
{
dfs(u,v);
}
}
}

void iniparent()
{
int k;
for(int i=1;i<=n;i++)
{
k=1;
if(pa[k-1][i]!=-1)
{
while(pa[k-1][pa[k-1][i]]!=-1)
{
pa[k][i]=pa[k-1][pa[k-1][i]];
k<<=1;
}
}
}
}

int lca(int v,int u)
{
if(depth[u]>depth[v])
{
swap(u,v);
}
if(depth[u]!=depth[v])
{
for(int i=max_log_n-1;i>=0;i--)
{
if(((depth[v]-depth[u])>>i)&1)
{
v=pa[i][v];
}
}
}
if(u==v)
{
return u;
}
else
{
for(int k=max_log_n-1;k>=0;k--)
{
if(pa[k][u]!=pa[k][v])
{
v=pa[k][v];
u=pa[k][u];
}
}
return pa[0][v];
}
}

void ini()
{
memset(pa,-1,sizeof(pa));
for(int i=0;i<maxn;i++)
{
es[i].to=-1;
es[i].next=-1;
}
memset(head,-1,sizeof(head));
}

int main()
{
//freopen("1.out","w",stdout);
ini();
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
int from,to;
scanf("%d%d",&from,&to);
addedge(from,to);
addedge(to,from);
}
s=1;
dfs(s,-1);
scanf("%d",&m);
//iniparent();
for(int j=1;j<=m;j++)
{
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dfs lca