LCA的两种写法

第一种是离线的Tarjan算法

#include<cstdio>
using namespace std;
int rd(){
int x=,fl=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-'){fl=-;}ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+(ch^);ch=getchar();}
return fl*x;
}
int n,m,s,x,y,num1,num2;
int f[],dis[],a[][],hd1[],hd2[];
bool vis[];
struct star{int nt,to,ds;}e[],e2[];
void add1(int from,int to){
e[++num1].nt=hd1[from];
e[num1].to=to;
hd1[from]=num1;
}
void add2(int from,int to,int ds){
e2[++num2].nt=hd2[from];
e2[num2].to=to;
e2[num2].ds=ds;
hd2[from]=num2;
}
int find(int x){
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
void un(int x,int y){
int ra=find(x),rb=find(y);
f[ra]=rb;
}
void tarjan(int x){
vis[x]=;
for(int i=hd2[x];i;i=e2[i].nt){
int to=e2[i].to,dis=e2[i].ds;
if(vis[to])
a[dis][]=find(to);
}
for(int i=hd1[x];i;i=e[i].nt){
int to=e[i].to;
if(!vis[to]){
tarjan(to);
un(to,x);
}
}
}
int main(){
n=rd();m=rd();s=rd();
for(int i=;i<n;i++){
x=rd();y=rd();
add1(x,y);add1(y,x);
}
for(int i=;i<=m;i++){
x=rd();y=rd();
a[i][]=x;a[i][]=y;
add2(x,y,i);add2(y,x,i);
}
for(int i=;i<=n;i++)f[i]=i;
tarjan(s);
for(int i=;i<=m;i++)
printf("%d\n",a[i][]);
return ;
}

这个代码跑的飞快但是不太好理解。。

还有一种用倍增的思想

#include<iostream>
#include<cstdio>
using namespace std;
int rd(){
int x=,fl=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-'){fl=-;}ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+(ch^);ch=getchar();}
return fl*x;
}
int n,m,x,y,s,num=,hd[],dep[],f[][];
struct star{int nt,to;}e[];
void add(int fm,int to){e[++num].to=to;e[num].nt=hd[fm];hd[fm]=num;}
void dfs(int x,int fa){
dep[x]=dep[fa]+;
for(int i=;i<=;i++)
f[x][i]=f[f[x][i-]][i-];
for(int i=hd[x];i;i=e[i].nt)
{
int to=e[i].to;
if(to==fa)continue;
f[to][]=x;
dfs(to,x);
}
}
int lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
for(int i=;i>=;i--){
if(dep[f[u][i]]>=dep[v])
u=f[u][i];
if(u==v)return u;
}
for(int i=;i>=;i--)
if(f[u][i]!=f[v][i]){
u=f[u][i];v=f[v][i];
}
return f[u][];
}
void print(int x){
if(x<){putchar('-');x=-x;}
if(x>)print(x/);
putchar(x%+'');
}
int main(){
n=rd();m=rd();s=rd();
for(int i=;i<n;i++){
x=rd();y=rd();
add(x,y);add(y,x);
}
dfs(s,);
for(int i=;i<=m;i++){
x=rd();y=rd();
print(lca(x,y));
putchar('\n');
}
return ;
}

emmm....这种比较好理解但是跑的有点慢...

如果不太懂...可以看这个/**/

其实还有一种bfs版的玄学算法也安利一下

/* */

上一篇:css3-11 如何改变背景图片的大小和位置


下一篇:pytorch查看模型weight与grad