POJ 1330 Nearest Common Ancestors (最近公共祖先LCA + 详解博客)
LCA问题 详细
1、二叉搜索树上找两个节点LCA
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public int query(Node t, Node u, Node v) { 2 int left = u.value; 3 int right = v.value; 4 5 //二叉查找树内,如果左结点大于右结点,不对,交换 6 if (left > right) { 7 int temp = left; 8 left = right; 9 right = temp; 10 } 11 12 while (true) { 13 //如果t小于u、v,往t的右子树中查找 14 if (t.value < left) { 15 t = t.right; 16 17 //如果t大于u、v,往t的左子树中查找 18 } else if (t.value > right) { 19 t = t.left; 20 } else { 21 return t.value; 22 } 23 } 24 }
2、二叉树上找两个节点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 node* getLCA(node* root, node* node1, node* node2) 2 { 3 if(root == null) 4 return null; 5 if(root== node1 || root==node2) 6 return root; 7 8 node* left = getLCA(root->left, node1, node2); 9 node* right = getLCA(root->right, node1, node2); 10 11 if(left != null && right != null) // 两个点在root的左右两边,就是root了 12 return root; 13 else if(left != null) // 哪边不空返回哪边 14 return left; 15 else if (right != null) 16 return right; 17 else 18 return null; 19 }
朴素法求解: 先对树进行dfs标出每一个节点的深度,对于查找的两个点先判断在不在同一深度,不在 移到统一深度,然后在往上找
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstdio> 5 #include <vector> 6 using namespace std; 7 const int Max = 10005; 8 int t, n, first, second, root; 9 vector<int> G[Max]; 10 int indegree[Max], depth[Max], father[Max]; 11 void inputTree() 12 { 13 for (int i = 0; i <= n; i++) 14 { 15 G[i].clear(); 16 father[i] = 0; 17 indegree[i] = 0; 18 depth[i] = 0; 19 } 20 int u, v; 21 for (int i = 1; i < n; i++) 22 { 23 scanf("%d%d", &u, &v); 24 G[u].push_back(v); 25 indegree[v]++; 26 father[v] = u; 27 } 28 scanf("%d%d", &first, &second); 29 for (int i = 1; i <= n; i++) 30 { 31 if (indegree[i] == 0) 32 { 33 root = i; 34 break; 35 } 36 } 37 } 38 void dfs_depth(int u, int dep) 39 { 40 depth[u] = dep; 41 int Size = G[u].size(); 42 for (int i = 0; i < Size; i++) 43 { 44 dfs_depth(G[u][i], dep + 1); 45 } 46 } 47 int find_ancestor() 48 { 49 while (depth[first] > depth[second]) 50 { 51 first = father[first]; 52 } 53 while (depth[first] < depth[second]) 54 { 55 second = father[second]; 56 } 57 while (first != second) // 这样直接返回first 58 { 59 first = father[first]; 60 second = father[second]; 61 } 62 return first; 63 } 64 int main() 65 { 66 scanf("%d", &t); 67 while (t--) 68 { 69 scanf("%d", &n); 70 inputTree(); 71 dfs_depth(root, 0); 72 printf("%d\n", find_ancestor()); 73 } 74 return 0; 75 }
tarjan + 并查集 解法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstdio> 5 #include <vector> 6 using namespace std; 7 const int Max = 10005; 8 int t, n, first, second, root; 9 vector<int> G[Max], querry[Max]; 10 int indegree[Max], father[Max], vis[Max]; 11 void inputTree() 12 { 13 for (int i = 0; i <= n; i++) 14 { 15 G[i].clear(); 16 querry[i].clear(); 17 father[i] = i; 18 indegree[i] = 0; 19 vis[i] = 0; 20 } 21 int u, v; 22 for (int i = 1; i < n; i++) 23 { 24 scanf("%d%d", &u, &v); 25 G[u].push_back(v); 26 indegree[v]++; 27 } 28 scanf("%d%d", &first, &second); 29 querry[first].push_back(second); 30 querry[second].push_back(first); 31 for (int i = 1; i <= n; i++) 32 { 33 if (indegree[i] == 0) 34 { 35 root = i; 36 break; 37 } 38 } 39 } 40 int find_father(int x) 41 { 42 if (x == father[x]) 43 return x; 44 return father[x] = find_father(father[x]); 45 } 46 void unionSet(int x, int y) 47 { 48 x = find_father(x); 49 y = find_father(y); 50 if (x != y) 51 father[y] = x; 52 } 53 void tarjan(int x) 54 { 55 int Size = G[x].size(); 56 for (int i = 0; i < Size; i++) 57 { 58 int v = G[x][i]; 59 tarjan(v); 60 unionSet(x, v); 61 } 62 vis[x] = 1; 63 /* 64 if (x == first && vis[second]) 65 printf("%d\n", find_father(second)); 66 else if (x == second && vis[first]) 67 printf("%d\n", find_father(first)); 68 */ 69 Size = querry[x].size(); 70 for (int i = 0; i < Size; i++) 71 { 72 if (vis[querry[x][i]]) 73 { 74 printf("%d\n", find_father(querry[x][i])); 75 return; 76 } 77 } 78 79 } 80 int main() 81 { 82 scanf("%d", &t); 83 while (t--) 84 { 85 scanf("%d", &n); 86 inputTree(); 87 tarjan(root); 88 } 89 return 0; 90 }