POJ 1330 Nearest Common Ancestors (最近公共祖先LCA + 详解博客)

LCA问题的tarjan解法模板

LCA问题 详细

 

1、二叉搜索树上找两个节点LCA


 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 }  
View Code

2、二叉树上找两个节点

 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 }  
View Code
朴素法求解: 先对树进行dfs标出每一个节点的深度,对于查找的两个点先判断在不在同一深度,不在 移到统一深度,然后在往上找
 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 }
View Code

tarjan + 并查集 解法:

 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 }
View Code

 

 

posted @ 2016-04-03 20:23  zhaop  阅读(166)  评论(0编辑  收藏  举报