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

猜你喜欢

转载自www.cnblogs.com/00isok/p/9813871.html