在有根树中,两个结点u和v的公共祖先中距离最近的那个称为最近公共祖先(lowest common ancestor)、
如图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 }