自己写的一个 模板,可以拿来参考一下
至于思路吗
大概就是dfs每一个节点
到一个节点的时候就打上标记,然后访问每个与这个节点有关的询问,对于每个询问,如果另一个节点是有标记的,则两点的最近公共祖先就是另一个节点的祖先
然后再遍历当前节点的每条边,dfs边的另一点,结束后再将另一点的祖先设置为当前点。<-这个比较重要,一定要是dfs之后再更换祖先
还有就是并查集的初始化一定不能忘记
#include<iostream>
#include<algorithm>
#define MAXN 500001
using namespace std;
int n,m,s;
struct line
{
int to;
int next;
}edge[MAXN*2];
struct query
{
int to;
int next;
int id;
}ques[MAXN*2];
int edgetot;
int quetot;
bool vis[MAXN];
int ans[MAXN];
int g[MAXN];
int qg[MAXN];
int pre[MAXN];
void addedge(int a,int b)
{
edgetot++;
edge[edgetot].to=b;
edge[edgetot].next=g[a];
g[a]=edgetot;
}
void addque(int a,int b,int i)
{
quetot++;
ques[quetot].to=b;
ques[quetot].id=i;
ques[quetot].next=qg[a];
qg[a]=quetot;
}
int find(int x)
{
if(x==pre[x])return x;
return pre[x]=find(pre[x]);
}
void dfs(int x)
{
vis[x]=true;
for(int i=qg[x];i;i=ques[i].next)
{
if(vis[ques[i].to]){ans[ques[i].id]=find(ques[i].to);}
}
for(int i=g[x];i;i=edge[i].next)
{
if(!vis[edge[i].to]){
dfs(edge[i].to);
pre[edge[i].to]=x;
}
}
return;
}
void init()
{
for(int i=1;i<=n;i++){
pre[i]=i;
vis[i]=false;
}
}
int main()
{
//std::ios::sync_with_stdio(false);
cin>>n>>m>>s;
for(int i=1;i<n;i++)
{
int x=0,y=0;
cin>>x>>y;
addedge(x,y);
addedge(y,x);
}
for(int i=0;i<m;i++)
{
int x=0,y=0;
cin>>x>>y;
addque(x,y,i);
addque(y,x,i);
}
init();
dfs(s);
for(int i=0;i<m;i++)
{
cout<<ans[i]<<endl;
}
return 0;
}