POJ 1330(LCA/倍增法模板)

链接:http://poj.org/problem?id=1330

题意:q次询问求两个点u,v的LCA

思路:LCA模板题,首先找一下树的根,然后dfs预处理求LCA(u,v)

AC代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<set>
 6 #include<string> 
 7 #include<vector>
 8 #include<stack>
 9 #include<queue> 
10 using namespace std;
11 typedef long long ll;
12 const int maxbit = 15;
13 const int maxn = 1e4+5;
14 vector<int> G[maxn];
15 int depth[maxn];
16 int fa[maxn][maxbit];
17 int Log[maxn];
18 int N;
19 void pre(){
20     Log[0] = -1;
21     Log[1] = 0,Log[2] = 1;
22     for(int i = 3;i<maxn;i++) Log[i] = Log[i/2] + 1;
23 } 
24 void dfs(int cur,int father){//dfs预处理 
25     depth[cur] = depth[father] + 1;//当前结点的深度为父亲结点+1 
26     fa[cur][0] = father;//更新当前结点的父亲结点 
27     for(int j = 1;(1<<j)<=N;j++){//倍增更新当前结点的祖先 
28         fa[cur][j] = fa[fa[cur][j-1]][j-1];
29     }
30     for(int i = 0;i<G[cur].size() ;i++){
31         if(G[cur][i] != father) {//dfs遍历 
32             dfs(G[cur][i],cur);
33         }
34     }
35 }
36 int LCA(int u,int v){
37     if(depth[u]<depth[v]) swap(u,v);
38     int dist = depth[u] - depth[v];//深度差 
39     while(depth[u]!=depth[v]){//把较深的结点u倍增到与v高度相等 
40         u = fa[u][Log[depth[u]-depth[v]]];
41     }
42     if(u == v) return u;//如果u倍增到v,说明v是u的LCA 
43     for(int i = Log[depth[u]];i>=0;i--){//否则两者同时向上倍增 
44         if(fa[u][i]!=fa[v][i]){//如果向上倍增的祖先不同,说明是可以继续倍增 
45             u = fa[u][i];//替换两个结点 
46             v = fa[v][i];
47         }
48     }
49     return fa[u][0];//最终结果为u v向上一层就是LCA 
50 } 
51 int main()
52 {
53     int t;
54     pre();
55     scanf("%d",&t);
56     while(t--){
57         scanf("%d",&N);
58         int root ;
59         int in[maxn]; 
60         for(int i = 0;i<maxn;i++){
61             G[i].clear() ;
62         }
63         memset(in,0,sizeof(in));
64         int u,v;
65         for(int i = 0;i<N-1;i++){
66             scanf("%d%d",&u,&v);
67             in[v] = 1;
68             G[u].push_back(v);
69             G[v].push_back(u);   
70         }
71         for(int i = 1;i<=N;i++){//寻树的根结点 
72             if(in[i] == 0) {
73                 root = i;
74                 break;
75             }
76         }
77         dfs(root,0);
78         scanf("%d%d",&u,&v);
79         int ans = LCA(u,v);
80         printf("%d\n",ans);
81     }
82     return 0;
83 }
84  
posted @ 2020-01-16 21:16  AaronChang  阅读(160)  评论(0编辑  收藏  举报