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\n", ans); 72 } 73 return 0; 74 }
倍增法代码如下:
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\n", lca(a, b)); 86 } 87 return 0; 88 }
奔跑吧!少年!趁着你还年轻