lca模板
也就是求树上两点的最近公共祖先。
我们采用树上倍增。
将两点跳至同一高度。
一起向上跳。
bfs(或dfs)预处理节点深度及节点的2的几次方的父亲。
代码:
#include <cstdio> #include <queue> #include <cmath> using namespace std; typedef long long int ll; const int maxn=100005; int n,m,s,tot,head[maxn],d[maxn],f[maxn][35],w; struct node{ int to,nxt; }t[maxn]; inline void add(const int x,const int y){ t[++tot].to=y;t[tot].nxt=head[x]; head[x]=tot; } queue<int>q; inline void bfs(const int s){ q.push(s); d[s]=1; while(q.size()){ int x=q.front();q.pop(); for(int i=head[x];i;i=t[i].nxt){ int y=t[i].to; if(d[y])continue; d[y]=d[x]+1; f[y][0]=x; for(int j=1;j<=w;j++){ f[y][j]=f[f[y][j-1]][j-1]; } q.push(y); } } } inline int lca(int x,int y){ if(d[y]>d[x])swap(x,y); for(int i=w;i>=0;i--){ if(d[f[x][i]]>=d[y]){ x=f[x][i]; } } if(x==y)return x; for(int i=w;i>=0;i--){ if(f[x][i]!=f[y][i]){ x=f[x][i]; y=f[y][i]; } } return f[x][0]; } int main(){ scanf("%d%d%d",&n,&m,&s); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } w=(int)(log(n)/log(2))+1; bfs(s); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); printf("%d ",lca(x,y)); } return 0; }