poj 1330 Nearest Common Ancestors (LCA)
题意:求两个点的近期公共祖先。
1A
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#define maxn 100010
using namespace std;
int fa[maxn],lev[maxn],pre[maxn],c1,c2;
vector<int> son[maxn];
bool dfs(int rt,int obj)
{
for(int i=0;i<son[rt].size();i++)
{
int t = son[rt][i];
pre[t] = rt;
lev[t] = lev[rt]+1;
if(t!=obj)
{
if(dfs(t,obj))
return true;
}
else return true;
}
return false;
}
void solve(int rt)
{
memset(lev,0,sizeof(lev));
dfs(rt,c1);
dfs(rt,c2);
pre[rt] = -1;
int x,y;
if(lev[c1]>=lev[c2])
{
x = c1;
y = c2;
}
else
{
x = c2;
y = c1;
}
while(lev[x]!=lev[y])
x = pre[x];
if(x==y)
printf("%d\n",y);
else
{
int k,l;
for(k=pre[x],l=pre[y];k!=l;k=pre[k],l=pre[l]);
printf("%d\n",k);
}
}
int main()
{
int T,n,a,b,rt;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
fa[i] = i;
son[i].clear();
}
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
son[a].push_back(b);
fa[b] = a;
}
scanf("%d%d",&c1,&c2);
for(int i=1;i<=n;i++)
{
if(fa[i]==i)
{
rt = i;
break;
}
}
solve(rt);
}
return 0;
}
tarjan离线LCA算法
算法流程:
Tarjan(u)
F(u)<-u;
For each (u,v) in Q(u) do Answer(u,v) <- F(v)
For each v in son(u)
a) Tarjan(v)。
b) F(v) <- u。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxn 100010
using namespace std;
int fa[maxn],anc[maxn],n,f,s,in[maxn];
bool vis[maxn];
vector<int> G[maxn];
void set_(int m)
{
fa[m] = m;
}
int root(int x) //带路径压缩的查找函数
{
if(fa[x]==x)
return x;
else fa[x] = root(fa[x]);
return fa[x];
}
void merge_(int a,int b)
{
int fx = root(a);
int fy = root(b);
if(fx!=fy)
fa[fy] = fx;
}
void LCA(int u) //tarjan离线算法
{
set_(u);
vis[u] = true;
if(u==s && vis[f])
{
printf("%d\n",root(f));
return;
}
if(u==f && vis[s])
{
printf("%d\n",root(s));
return ;
}
for(int i=0;i<G[u].size();i++)
{
int v = G[u][i];
if(!vis[v])
{
LCA(v);
fa[v] = u;
}
}
}
int main()
{
int T,a,b;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
G[i].clear();
in[i] = 0;
}
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
G[a].push_back(b);
in[b]++; //统计入度,由于有根树根不同找到的LCA也不同
}
memset(vis,0,sizeof(vis));
scanf("%d%d",&f,&s);
int rt;
for(int i=1;i<=n;i++)
{
if(!in[i])
{
rt = i;
break;
}
}
LCA(rt);
}
return 0;
}

浙公网安备 33010602011771号