*树上倍增(LCA)

xiaoxiao2021-02-28  96

今天是2017/7/10,DCDCBigBig的第二十三篇博文

树上倍增(LCA)

#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; struct edge{ int v,next; }a[100001]; int n,q,u,v,rt,tot=0,head[100001],fa[100001][31],dep[100001]; bool vis[100001]; void add(int u,int v){ a[++tot].v=v; a[tot].next=head[u]; head[u]=tot; } void cal_dep(int u){ vis[u]=true; for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){ int v=a[tmp].v; if(!vis[v]){ dep[v]=dep[u]+1; cal_dep(v); } } } void cal(){ for(int j=1;j<=30;j++){ for(int i=1;i<=n;i++){ fa[i][j]=fa[fa[i][j-1]][j-1]; } } } int lca(int x,int y){ if(dep[x]<dep[y]){ swap(x,y); } int s=dep[x]-dep[y]; for(int i=0;i<30;i++){ if((1<<i)&s)x=fa[x][i]; } if(x==y)return x; for(int i=29;i>=0;i--){ if(fa[x][i]!=fa[y][i]){ x=fa[x][i]; y=fa[y][i]; } } return fa[x][0]; } int main(){ memset(head,-1,sizeof(head)); memset(fa,0,sizeof(fa)); memset(dep,0,sizeof(dep)); memset(vis,0,sizeof(vis)); scanf("%d%d",&n,&q); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); add(u,v); fa[v][0]=u; } dep[1]=1; cal_dep(1); cal(); for(int i=1;i<=q;i++){ scanf("%d%d",&u,&v); printf("%d\n",lca(u,v)); } return 0; } /* 16 4 1 2 1 3 2 4 2 5 2 6 3 7 4 8 4 9 5 10 7 11 7 12 10 13 10 14 10 15 12 16 4 7 9 16 11 16 15 8 ------ 1 1 7 2 */

转载请注明原文地址: https://www.6miu.com/read-29381.html

最新回复(0)