poj 1330 (简单LCA 暴力法 / 倍增法)

题意:现实给你一棵树然后给你树上的n-1条边,接着给你一对顶点,然后让你求这对顶点的LCA。

思路:由于刚刚学习LCA所以找了这一道最最水的LCA题目来做发现用复杂度较高的算法也能过,就是先遍历求出每个结点的父亲和深度,然后再将深度深的向上走,一直走到两个结点在同一高度上。再两个节点一起往上走,直到走到一个节点那么这个节点即为那两个节点的LCA。

暴力法代码如下:

 1 //LCA
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <cstring>
 7 #include <algorithm>
 8 #include <queue>
 9 #include <stack>
10 #include <vector>
11 #include <set>
12 #include <map>
13 #define MP(a, b) make_pair(a, b)
14 #define PB(a) push_back(a)
15 
16 using namespace std;
17 
18 typedef long long ll;
19 typedef pair<int ,int> pii;
20 typedef pair<unsigned int, unsigned int> puu;
21 typedef pair<int ,double> pid;
22 typedef pair<ll, int> pli;
23 
24 const int INF = 0x3f3f3f3f;
25 const double eps = 1e-6;
26 const int LEN = 100000+10;
27 vector<int> Map[LEN];
28 int root, ind[LEN], depth[LEN], parent[LEN];
29 
30 void dfs(int v, int p, int d){
31     parent[v] = p;
32     depth[v] = d;
33     for(int i=0; i<Map[v].size(); i++){
34         if(Map[v][i] != p)dfs(Map[v][i], v, d+1);
35     }
36 }
37 
38 void init() {dfs(root, -1, 0);}
39 
40 int lca(int u, int v){
41     while(depth[u] > depth[v]) u = parent[u];
42     while(depth[v] > depth[u]) v = parent[v];
43     while(u!=v){
44         u = parent[u];
45         v = parent[v];
46     }
47     return u;
48 }
49 
50 int main()
51 {
52 //    freopen("in.txt", "r", stdin);
53 
54     int n, a, b, T;
55     scanf("%d", &T);
56     while(T--){
57         for(int i=0; i<LEN; i++)Map[i].clear();
58         memset(ind, 0, sizeof ind);
59         scanf("%d", &n);
60         for(int i=0; i<n-1; i++){
61             scanf("%d%d", &a, &b);
62             Map[a].PB(b);
63             Map[b].PB(a);
64             ind[b]++;
65         }
66         for(int i=1; i<=n; i++)
67             if(ind[i]==0) {root = i;break;}
68         init();
69         scanf("%d%d", &a, &b);
70         int ans = lca(a, b);
71         printf("%d
", ans);
72     }
73     return 0;
74 }
View Code

倍增法代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <stack>
 9 #include <vector>
10 #include <set>
11 #include <map>
12 #define MP(a, b) make_pair(a, b)
13 #define PB(a) push_back(a)
14 
15 using namespace std;
16 
17 typedef long long ll;
18 typedef pair<int ,int> pii;
19 typedef pair<unsigned int, unsigned int> puu;
20 typedef pair<int ,double> pid;
21 typedef pair<ll, int> pli;
22 
23 const int INF = 0x3f3f3f3f;
24 const double eps = 1e-6;
25 const int LEN = 100010;
26 const int LOG_LEN = 22;
27 vector<int> Map[LEN];
28 int ind[LEN], root, parent[LOG_LEN][LEN], depth[LEN];
29 
30 void dfs(int v, int p, int d)
31 {
32     depth[v] = d;
33     parent[0][v] = p;
34     for(int i=0; i<Map[v].size(); i++){
35         if(Map[v][i]!=p) dfs(Map[v][i], v, d+1);
36     }
37 }
38 
39 void init(int n)
40 {
41     dfs(root, -1, 0);
42     for(int k=0; k+1<LOG_LEN; k++){
43         for(int i=1; i<=n; i++){
44             if(parent[k][i] < 0) parent[k+1][i] = -1;
45             else parent[k+1][i] = parent[k][parent[k][i]];
46         }
47     }
48 }
49 
50 int lca(int u, int v)
51 {
52     if(depth[u] > depth[v]) swap(u, v);
53     for(int i=0; i<LOG_LEN; i++){
54         if((depth[v]-depth[u]) >> i & 1) v = parent[i][v];
55     }
56     if(u==v) return u;
57     for(int i=LOG_LEN-1; i>=0; i--){
58         if(parent[i][u]!=parent[i][v]){
59             v = parent[i][v];
60             u = parent[i][u];
61         }
62     }
63     return parent[0][u];
64 }
65 
66 int main()
67 {
68 //    freopen("in.txt", "r", stdin);
69 
70     int T, n, a, b;
71     scanf("%d", &T);
72     while(T--){
73         scanf("%d", &n);
74         memset(ind, 0, sizeof ind);
75         for(int i=0; i<LEN; i++)Map[i].clear();
76         for(int i=0; i<n-1; i++){
77             scanf("%d%d", &a, &b);
78             Map[a].PB(b);
79             Map[b].PB(a);
80             ind[b]++;
81         }
82         for(int i=1; i<=n; i++)if(!ind[i]){root = i;break;}
83         init(n);
84         scanf("%d%d", &a, &b);
85         printf("%d
", lca(a, b));
86     }
87     return 0;
88 }
View Code
奔跑吧!少年!趁着你还年轻
原文地址:https://www.cnblogs.com/shu-xiaohao/p/3529591.html