1. 程式人生 > >POJ 1330 Nearest Common Ancestors (模板題) (LCA)【倍增】

POJ 1330 Nearest Common Ancestors (模板題) (LCA)【倍增】

<題目連結>

題目大意:

給出一棵樹,問任意兩個點的最近公共祖先的編號。

解題分析:
LCA模板題,下面用的是線上倍增演算法求解。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 using namespace std;
 6 
 7 const int N = 1e4+10;
 8 const int INF = 0x3f3f3f3f;
 9 struct Edge{
10     int to,next;
11 }edge[N<<1]; 12 int cnt,head[N]; 13 int dep[N],f[N][35]; 14 int n,in[N]; 15 void addedge(int u,int v){ 16 edge[++cnt].to=v,edge[cnt].next=head[u]; 17 head[u]=cnt; 18 } 19 void dfs(int u,int fa){ //將所有節點的深度都標記出來 20 for(int i=head[u];~i;i=edge[i].next){ 21 int v=edge[i].to;
22 if(v==fa)continue; 23 if(!dep[v]){ 24 dep[v]=dep[u]+1; 25 f[v][0]=u; 26 dfs(v,u); 27 } 28 } 29 } 30 void init(){ //預處理倍增陣列 31 for(int j=1;(1<<j)<=n;j++) 32 for(int i=1;i<=n;i++) 33 f[i][j]=f[f[i][j-1
]][j-1]; 34 } 35 int LCA(int x,int y){ 36 if(dep[x]<dep[y])swap(x,y); 37 int d=dep[x]-dep[y]; 38 for(int i=0;(d>>i)!=0;i++) 39 if((d>>i)&1)x=f[x][i]; 40 if(x==y)return x; 41 for(int i=20;i>=0;i--) 42 if(f[x][i]!=f[y][i]){ 43 x=f[x][i]; 44 y=f[y][i]; 45 } 46 return f[x][0]; 47 } 48 int main(){ 49 int T;scanf("%d",&T); 50 while(T--){ 51 scanf("%d",&n); 52 cnt=0; 53 int u,v; 54 memset(head,-1,sizeof(head)); 55 for(int i=1;i<n;i++){ 56 scanf("%d%d",&u,&v); 57 addedge(u,v); 58 in[v]++; 59 } 60 memset(dep,0,sizeof(dep)); 61 int root; 62 for(int i=1;i<=n;i++) 63 if(!in[i])root=i; //找到該樹的根 64 dep[root]=1; 65 dfs(root,-1); 66 init(); 67 scanf("%d%d",&u,&v); 68 printf("%d\n",LCA(u,v)); 69 } 70 return 0; 71 }

 

 

2018-10-18