2013-team4/code/lca
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
LCA 倍增算法
时间复杂度: O(NlogN),空间复杂度: O(NlogN)
#include <iostream>
#include <cstdio>
#include <memory.h>
#define MAXN 10010
int head[MAXN],next[MAXN],link[MAXN];
int dep[MAXN],f[MAXN][16];
int n,root;
int u,v;
void dfs(int u)
{
int now;
now=head[u];
while (now>0)
{
f[link[now]][0]=u;
dep[link[now]]=dep[u]+1;
dfs(link[now]);
now=next[now];
}
}
void build()
{
int i,j;
for (j=1;1<<j<=n;j++)
for (i=1;i<=n;i++)
if (f[i][j-1]>0)
f[i][j]=f[f[i][j-1]][j-1];
}
int lca(int u,int v)
{
int i, log;
if (dep[u]<dep[v])
i=u, u=v, v=i;
for (log=1;1<<log<=n;log++);
for (i=log;i>=0;i--)
if (dep[u]-(1<<i)>=dep[v])
{
u=f[u][i];
if (u==v) return u;
}
for (i=log;i>=0;i--)
if (f[u][i]!=-1&&f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
return f[u][0];
}
int main()
{
int test,i;
scanf("%d",&test);
while (test--)
{
scanf("%d",&n);
root=n*(n+1)/2;
memset(head,-1,sizeof(head));
memset(next,-1,sizeof(next));
memset(f,-1,sizeof(f));
for (i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
next[i]=head[u];
head[u]=i;
link[i]=v;
root-=v;
}
scanf("%d%d",&u,&v);
dep[root]=0;
dfs(root);
build();
printf("%d\n",lca(u,v));
}
return 0;
}
}}}
{{{
Tarjan+并查集
待补
}}}
LCA 倍增算法
时间复杂度: O(NlogN),空间复杂度: O(NlogN)
#include <iostream>
#include <cstdio>
#include <memory.h>
#define MAXN 10010
int head[MAXN],next[MAXN],link[MAXN];
int dep[MAXN],f[MAXN][16];
int n,root;
int u,v;
void dfs(int u)
{
int now;
now=head[u];
while (now>0)
{
f[link[now]][0]=u;
dep[link[now]]=dep[u]+1;
dfs(link[now]);
now=next[now];
}
}
void build()
{
int i,j;
for (j=1;1<<j<=n;j++)
for (i=1;i<=n;i++)
if (f[i][j-1]>0)
f[i][j]=f[f[i][j-1]][j-1];
}
int lca(int u,int v)
{
int i, log;
if (dep[u]<dep[v])
i=u, u=v, v=i;
for (log=1;1<<log<=n;log++);
for (i=log;i>=0;i--)
if (dep[u]-(1<<i)>=dep[v])
{
u=f[u][i];
if (u==v) return u;
}
for (i=log;i>=0;i--)
if (f[u][i]!=-1&&f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
return f[u][0];
}
int main()
{
int test,i;
scanf("%d",&test);
while (test--)
{
scanf("%d",&n);
root=n*(n+1)/2;
memset(head,-1,sizeof(head));
memset(next,-1,sizeof(next));
memset(f,-1,sizeof(f));
for (i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
next[i]=head[u];
head[u]=i;
link[i]=v;
root-=v;
}
scanf("%d%d",&u,&v);
dep[root]=0;
dfs(root);
build();
printf("%d\n",lca(u,v));
}
return 0;
}
Tarjan+并查集
待补