首页 > 代码库 > LCA 倍增
LCA 倍增
最近公共祖先
对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int n,q; 7 int cnt,head[500],r[500],deep[500],p[500][10]; 8 struct node{ 9 int v; 10 int next; 11 }s[500]; 12 13 void add(int u,int v){ 14 s[++cnt].v=v; 15 s[cnt].next=head[u]; 16 head[u]=cnt; 17 } 18 19 void DFS(int x){//预处理深度 20 for(int i=head[x];i;i=s[i].next){ 21 int V=s[i].v; 22 if(!deep[V]){ 23 deep[V]=deep[x]+1; 24 p[V][0]=x; 25 DFS(V); 26 } 27 } 28 } 29 30 void init(){//p[i][j]表示i的第2^j的祖先 31 for(int j=1;(1<<j)<=n;++j) 32 for(int i=1;i<=n;++i) 33 if(p[i][j-1]!=-1) 34 p[i][j]=p[p[i][j-1]][j-1];//i的2^j的祖先-->i的2^(j-1)的祖先的2^(j-1)的祖先 35 } 36 37 int LCA(int a,int b){ 38 if(deep[a]<deep[b])swap(a,b); 39 int i; 40 for(i=0;(1<<i)<=deep[a];++i); 41 --i; 42 for(int j=i;j>=0;--j)//使a,b在相同深度 43 if(deep[a]-(1<<j)>=deep[b])a=p[a][j]; 44 if(a==b)return a; 45 for(int j=i;j>=0;--j)//LCA 46 if(p[a][j]!=-1&&p[a][j]!=p[b][j]){ 47 a=p[a][j]; 48 b=p[b][j]; 49 } 50 return p[a][0]; 51 } 52 53 int main(){ 54 scanf("%d",&n); 55 for(int i=1;i<n;++i){ 56 int x,y; 57 scanf("%d%d",&x,&y); 58 ++r[y]; 59 add(x,y); 60 } 61 int rt; 62 for(int i=1;i<=n;++i)if(r[i]==0){rt=i;break;} 63 memset(p,-1,sizeof(p)); 64 p[rt][0]=rt; 65 DFS(rt); 66 init(); 67 68 scanf("%d",&q); 69 for(int i=1;i<=q;++i){ 70 int x,y; 71 scanf("%d%d",&x,&y); 72 printf("%d\n",LCA(x,y)); 73 } 74 return 0; 75 }
LCA 倍增
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。