秘籍之树上蹦迪--LCA
炒鸡炒鸡炒鸡经典的模板题!
直接上代码啦
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <ctime> #define maxn 500000 using namespace std; int n,m,s,u,v,num; int fir[maxn*2],d[maxn*2],p[maxn*2][21]; struct qwq { int to; int next; }e[maxn*4]; int read() { int x=0;char ch=' '; while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x; } void addedge(int u,int v) { num++; e[num].to=v; e[num].next=fir[u]; fir[u]=num; } void dfs(int u,int fa) { d[u]=d[fa]+1;p[u][0]=fa; for(int i=1;(1<<i)<=d[u];i++) { p[u][i]=p[p[u][i-1]][i-1]; } for(int i=fir[u];i;i=e[i].next) { if(e[i].to!=fa) dfs(e[i].to,u); } } int lca(int u,int v) { if(d[u]>d[v]) swap(u,v); for(int i=20;i>=0;--i) { if(d[u]<=d[v]-(1<<i)) v=p[v][i]; } if(u==v) return u; for(int i=20;i>=0;--i) { if(p[u][i]==p[v][i])continue; u=p[u][i];v=p[v][i]; } return p[u][0]; } int main() { n=read();m=read();s=read(); for(int i=1;i<n;++i) { u=read();v=read(); addedge(u,v);addedge(v,u); } dfs(s,0); for(int i=1;i<=m;++i) { u=read();v=read(); printf("%d\n",lca(u,v)); } return 0; }
稍微有点疑惑的是为什么节点上跳2^i时不用重新遍历新节点上移2^i,因为2^(i-1)+2^(i-1)=2^i啦,树的深度一般一般一般不会超过2^20啦