经过学习和(抄袭)学会了lca倍增。
跳表?acs[x][i]:x上2 i步的祖先
每次查找最大能减去2 i 提到同一高度
然后再一起上升找到祖先
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int n,m,u,v;
int used[100010],dis[100010],dep[100010];
int acs[100010][23];
vector<int>graph[100010];
void dfs(int u,int d)
{
used[u]=1;
dep[u]=d;
for(int i=0;i<graph[u].size();i++)
{
int v=graph[u][i];
if(!used[v])
{
acs[v][0]=u;
dfs(v,d+1);
}
}
}
void get_acs()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=22;j++)
{
if(acs[i][j-1]<0)
acs[i][j]=-1;
else
acs[i][j]=acs[acs[i][j-1]][j-1];
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])
swap(x,y);
for(int k=22;k>=0;k--)
{
if(acs[x][k]!=-1&&dep[acs[x][k]]>=dep[y])
x=acs[x][k];
}
if(x==y)
return x;
for(int k=22;k>=0;k--)
{
if(acs[x][k]!=acs[y][k])
{
x=acs[x][k];
y=acs[y][k];
}
}
return acs[x][0];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>u>>v;
graph[u].push_back(v);
graph[v].push_back(u);
}
memset(acs,-1,sizeof(acs));
dfs(1,1);
get_acs();
while(cin>>u>>v)
{
cout<<lca(u,v)<<endl;
}
return 0;
}