在有根树中,两个结点u和v的公共祖先中距离最近的那个称为最近公共祖先(lowest common ancestor)、

LCA算法

如图lca(4,7) = 2, lca(6,8)=1, lca(5,8)=5

记点v到根的深度为depth[v], 那么如果w是点u和v的公共祖先的话, 让u向上走depth[u] - depth[w]步,让v向上走depth[v]-depth[w]步,都将走到w

因此让u和v中较深的一个向上走|depth[u]-depth[v]|步,然后再一步步向上走,直到走到同一个结点,就可以再O(n)的时间内求出LCA

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <string>
12 #include <math.h>
13 using namespace std;
14 #pragma warning(disable:4996)
15 typedef long long LL;                   
16 const int INF = 1<<30;
17 /*
18 8 7
19 1 2
20 1 3
21 2 4
22 2 5
23 5 7
24 5 8
25 3 6
26 */
27 const int N = 1000 + 10;
28 vector<int> g[N];
29 int parent[N],depth[N];
30 void dfs(int u, int p, int d)//求出每个点的depth和parent
31 {
32     parent[u] = p;
33     depth[u] = d;
34     for(int i=0; i<g[u].size(); ++i)
35     {
36         if(g[u][i]!=p)
37             dfs(g[u][i],u,d+1);
38     }
39 }
40 void init()
41 {
42     dfs(1,-1,0);
43 }
44 int lca(int u, int v)
45 {
46     //让u和v向上走到同一深度
47     while(depth[u] > depth[v]) u = parent[u] ;
48     while(depth[v] > depth[u]) v = parent[v] ;
49     //让u和v走到同一结点
50     while(u!=v)
51     {
52         u = parent[u];
53         v = parent[v];
54     }
55     return u;
56 }
57 int main()
58 {
59     int n,m,i,a,b;
60     while(scanf("%d%d",&n,&m)!=EOF)
61     {
62         for(i=0; i<m; ++i)
63         {
64             scanf("%d%d",&a,&b);
65             g[a].push_back(b);
66             g[b].push_back(a);
67         }
68         init();
69         while(scanf("%d%d",&a,&b)!=EOF)
70         {
71             printf("%d\n",lca(a,b));
72         }
73     }
74     return 0;
75 }
View Code

相关文章: