#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pi acos(-1.0)
#define e exp(1.0)
const ll maxn=50;
vector<ll>G[maxn];
ll parent[maxn];
ll depth[maxn];
ll root;
//预处理出来父节点和深度
void DFS(ll v,ll p,ll d)//argument:当前节点 父节点 当前节点的深度
{
depth[v]=d;
parent[v]=p;
ll i,u;
for(i=0;i<G[v].size();i++)
{
u=G[v][i];
if(u!=p)
DFS(u,v,d+1);
}
return ;
}
ll LCA(ll u,ll v)
{
if(u==v)
return u;
//先让u,v上升到同样高度
if(depth[u]<depth[v])//每次让u向v看齐
swap(u,v);
while(depth[u]!=depth[v])
u=parent[u];
while(u!=v)
{
u=parent[u];
v=parent[v];
}
return u;
}
int main()
{
// freopen(".../.txt","w",stdout);
ios::sync_with_stdio(false);
ll i,j,N,M,u,v;
cin>>N>>M;
for(i=0;i<M;i++)
{
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
cin>>root>>u>>v;
memset(parent,-1,sizeof(parent));
DFS(root,-1,0);
ll jie=LCA(u,v);
cout<<jie<<endl;
return 0;
}
![](https://img-blog.csdnimg.cn/20200224205109527.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMxMTY5NQ==,size_16,color_FFFFFF,t_70)
```c
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pi acos(-1.0)
#define e exp(1.0)
const ll maxn=50;
const ll maxk=5;
vector<ll>G[maxn];
ll parent[maxk][maxn];//parent[k][i]:节点i向上走2^k步到达的节点,超过根节点是记为-1
ll depth[maxn];
ll root,N,M,res=0,K;//argument:树的根 顶点 边数 深度 K=floor(log_2(res));
//预处理出来父节点和深度
void DFS(ll v,ll p,ll d)//argument:当前节点 父节点 当前节点的深度
{
depth[v]=d;
res=max(res,depth[v]);
parent[0][v]=p;
ll i,u;
for(i=0;i<G[v].size();i++)
{
u=G[v][i];
if(u!=p)
DFS(u,v,d+1);
}
return ;
}
//预处理出来parent数组
void Init()
{
ll i,j;
for(i=0;i+1<=K;i++)//这两层循环的顺序不能颠倒,也类似与动态数组,递推的关系决定的
{
for(j=1;j<=N;j++)
{
if(parent[i][j]<0)
parent[i+1][j]=-1;
else
parent[i+1][j]=parent[i][parent[i][j]];
}
}
return ;
}
ll LCA(ll u,ll v)
{
if(u==v)
return u;
//将u上升到和v一样的高度
if(depth[u]<depth[v])
swap(u,v);
//比如说两个节点的深度差用二进制是100111101,循环的作用似遍历每一二进制位将对应的1去掉,从而减小高度差
for(ll k=K;k>=0;k--)
{
if((depth[u]-depth[v])>>k&1)
u=parent[k][u];
}
if(u==v)
return u;
//利用二分搜索计算LCA
for(ll k=K;k>=0;k--)
{
if(parent[k][u]!=parent[k][v])
{
u=parent[k][u];
v=parent[k][v];
}
}
return parent[0][u];
}
int main()
{
// freopen(".../.txt","w",stdout);
ios::sync_with_stdio(false);
ll i,j,u,v;
cin>>N>>M;
for(i=0;i<M;i++)
{
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
cin>>u>>v>>root;
// memset(parent,-1,sizeof(parent));
DFS(root,-1,0);
//math库中只支持log()函数:以e为底 log10():以10为底,这里用了对数的换底公式
//但是这样计算可能有误差,但是可能性很小,保险起见可以将floor改为ceil
K=ceil(log(res)/log(2));
ll jie=LCA(u,v);
cout<<jie<<endl;
return 0;
}
来源:CSDN
作者:嘘……一只bug
链接:https://blog.csdn.net/weixin_43311695/article/details/104485129