LCA
\(LCA\)=最近公共祖先。
1.初始化\(lg\)数组,其代表\(lg2+1\)。
2.利用倍增的思想去求\(fa[u][i]\),在\(u\)点向上走\(2^i\)步时的祖先是谁。深度\(dep\)也同时求出。
3.初始化\(fa[u][0]=father\)
4.\(LCA\)
int LCA(int x,int y){
if(dep[x]<dep[y])
swap(x,y);
while(dep[x]>dep[y]){
x=fa[x][lg[dep[x]-dep[y]]-1];//一直跳直到深度相同
}
if(x==y)return x;
for(int k=lg[dep[x]]-1;k>=0;--k){
if(fa[x][k]!=fa[y][k])//向上跳从大->小,第一个不相等的点就是公共祖先的儿子
x=fa[x][k],y=fa[y][k];
}
return fa[x][0];
P3379 【模板】最近公共祖先(LCA)
#include<bits/stdc++.h>
using namespace std;
//#define int long long
int n,m,s;
const int maxn=5e5+10;
int head[maxn],tot=0;
struct edge{
int to,next;
}edge[maxn<<1];
void add(int u,int v){
edge[++tot].to=v;
edge[tot].next=head[u];
head[u]=tot;
}
int dep[maxn],fa[maxn][22],lg[maxn];
void dfs(int u,int father){
dep[u]=dep[father]+1;
fa[u][0]=father;
for(int i=1;i<=lg[dep[u]];++i){
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==father)continue;
dfs(v,u);
}
}
int LCA(int x,int y){
if(dep[x]<dep[y])
swap(x,y);
while(dep[x]>dep[y]){
x=fa[x][lg[dep[x]-dep[y]]-1];
}
if(x==y)return x;
for(int k=lg[dep[x]]-1;k>=0;--k){
if(fa[x][k]!=fa[y][k])
x=fa[x][k],y=fa[y][k];
}
return fa[x][0];
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m>>s;
for(int i=1;i<n;++i){
int x,y;cin>>x>>y;
add(x,y);add(y,x);
}
for(int i=1;i<maxn;++i){
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
}
dfs(s,0);
for(int i=1;i<=m;++i){
int a,b;cin>>a>>b;
cout<<LCA(a,b)<<endl;
}
}
P4281[AHOI2008]紧急集合、聚会
思路
求三个点的\(lca\),\(xy,xz,yz\)。我们容易知道的是必有两个\(lca\)是相等的(画图易得),然后我们选择不相等的那个\(lca\)作为最终的终点可。(画图易得)
#include<bits/stdc++.h>
using namespace std;
//#define int long long
int n,m,s;
const int maxn=5e5+10;
int head[maxn],tot=0;
struct edge{
int to,next;
}edge[maxn<<1];
void add(int u,int v){
edge[++tot].to=v;
edge[tot].next=head[u];
head[u]=tot;
}
int dep[maxn],fa[maxn][22],lg[maxn];
void dfs(int u,int father){
dep[u]=dep[father]+1;
fa[u][0]=father;
for(int i=1;i<=lg[dep[u]];++i){
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==father)continue;
dfs(v,u);
}
}
int LCA(int x,int y){
if(dep[x]<dep[y])
swap(x,y);
while(dep[x]>dep[y]){
x=fa[x][lg[dep[x]-dep[y]]-1];
}
if(x==y)return x;
for(int k=lg[dep[x]]-1;k>=0;--k){
if(fa[x][k]!=fa[y][k])
x=fa[x][k],y=fa[y][k];
}
return fa[x][0];
}
signed main(){
// ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//cin>>n>>m;
scanf("%d%d",&n,&m);
for(int i=1;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
for(int i=1;i<maxn;++i){
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
}
dfs(1,0);
for(int i=1;i<=m;++i){
int x,y,z;
// cin>>x>>y>>z;
scanf("%d%d%d",&x,&y,&z);
int xy=LCA(x,y),xz=LCA(x,z),yz=LCA(y,z);
int ans;
if(xy==xz){
ans=dep[x]+dep[y]+dep[z]-dep[yz]-dep[yz]-dep[xz]+dep[yz]-dep[xz];
printf("%d %d\n",yz,ans);
// cout<<yz<<" "<<ans<<endl;
}else if(xy==yz){
ans=dep[x]+dep[y]+dep[z]-dep[xz]-dep[xz]-dep[xy]+dep[xz]-dep[yz];
printf("%d %d\n",xz,ans);
}else{
ans=dep[x]+dep[y]+dep[z]-dep[xy]-dep[xy]-dep[xz]+dep[xy]-dep[xz];
printf("%d %d\n",xy,ans);
}
}
}