方法1:倍增
1498ms
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; typedef long long ll; const int N=5e5+5; inline int read(){ char c=getchar();int x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } int n,q,root,a,b; struct edge{ int v,ne; }e[N<<1]; int cnt=0,h[N]; inline void ins(int u,int v){ cnt++; e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt; cnt++; e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt; } int fa[N][21],deep[N],vis[N]; void dfs(int u){ vis[u]=1; for(int j=1;(1<<j)<=deep[u];j++) fa[u][j]=fa[fa[u][j-1]][j-1]; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(vis[v]) continue; deep[v]=deep[u]+1; fa[v][0]=u; dfs(v); } } int lca(int x,int y){ if(deep[x]<deep[y]) swap(x,y); int bin=deep[x]-deep[y]; for(int i=0;i<=16;i++) if((1<<i)&bin) x=fa[x][i];//,printf("x %d\n",i); for(int i=16;i>=0;i--) if(fa[x][i]!=fa[y][i]){ x=fa[x][i]; y=fa[y][i]; } if(x==y) return x; else return fa[x][0]; } int main(int argc, const char * argv[]) { n=read();q=read();root=read(); for(int i=1;i<=n-1;i++) a=read(),b=read(),ins(a,b); dfs(root); for(int i=1;i<=q;i++){ a=read();b=read(); printf("%d\n",lca(a,b)); } return 0; }
方法2:树链剖分
1314ms
让链首深度大的走到重链的父节点直到在一条重链上,返回深度小的节点
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; typedef long long ll; const int N=5e5+5; inline int read(){ char c=getchar();int x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } int n,q,root,a,b; struct edge{ int v,ne; }e[N<<1]; int cnt=0,h[N]; inline void ins(int u,int v){ cnt++; e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt; cnt++; e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt; } int fa[N],deep[N],mx[N],size[N]; void dfs(int u){ size[u]++; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(v==fa[u]) continue; fa[v]=u;deep[v]=deep[u]+1; dfs(v); size[u]+=size[v]; if(size[v]>size[mx[u]]) mx[u]=v; } } int tid[N],top[N],tot; void dfs(int u,int anc){ if(!u) return; tid[u]=++tot;top[u]=anc; dfs(mx[u],anc); for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(v!=fa[u]&&v!=mx[u]) dfs(v,v); } } int lca(int x,int y){ while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]]) swap(x,y); x=fa[top[x]]; } if(deep[x]>deep[y]) swap(x,y); return x; } int main(int argc, const char * argv[]) { n=read();q=read();root=read(); for(int i=1;i<=n-1;i++) a=read(),b=read(),ins(a,b); dfs(root); dfs(root,root); for(int i=1;i<=q;i++){ a=read();b=read(); printf("%d\n",lca(a,b)); } return 0; }
时间: 2024-10-03 20:16:02