The nearest ancestor of any two points on the tree must be the least depth of the shortest path of the two nodes.
For example, in nodes 7 and 5, the shortest path is 7--4--1--5, and the smallest point on the path is node 1, with a depth of 1. Node 1 is the LCA for nodes 7 and 5.
Therefore, to find any two-node LCA, we need to find the shortest path above, and then find the least depth point in the shortest path. And this is what the LCA online algorithm does.
LCA Online Algorithm Description (example):
1. Get "Shortest path" (not really a path, including other nodes, but without affecting the correctness of the algorithm)
Using DFS to traverse the entire tree, get the following data:
(1) Traversal sequence p:0 1 3 1 4 7 4 8 4 1 5 1 0 2 6 2 0
(2) Depth sequence of each node depth:0 1 1 2 2 2 2 3 3
(3) The position sequence of the first occurrence of each node in sequence p pos:0 1 13 2 4 10 14 5 7
With the above data, let's say we now require the shortest path for nodes 7 and 5, and we can do this:
(1) First, obtained from the POS sequence node 7 and node 5 in the P sequence the first occurrence of the position is: pos[7] = 5, pos[5] = 10;
(2) Get P sequence [5, 10] This satin sequence s:7 4 8 4 1 5
(3) The smallest point in the s sequence, i.e. node 1, is the LCA of node 7 and node 5 we are looking for.
Notice that the S sequence at this time is not a shortest path from node 7 to node 5, it contains some other nodes in addition to the nodes on the shortest path of 7 to 5, but these other nodes are nodes on the subtree rooted in Node 1, their depth is greater than the node 1, Does not affect our algorithm to solve the correct results.
2. How to quickly get the least depth node in a sequence
The problem of solving the most value of interval is the classical RMQ problem we are familiar with, and the rmq-st algorithm can be used. Because the rmq-st algorithm is online, our LCA algorithm is also online.
Here is my Code implementation:
1#include <iostream>2#include <string>3#include <map>4#include <vector>5#include <algorithm>6#include <cmath>7 8 using namespacestd;9 Ten #defineMAXN 100005 One Amap<string,int>MP; - stringname[2*MAXN]; -vector<int> v[2*MAXN]; the intp[4*MAXN], depth[2*MAXN], pos[2*MAXN]; - intpre_cal[4*maxn][ -]; - intCNT, N, m; - + voidDfsintIintd) - { +Pos[i] =CNT; Ap[cnt++] =i; atDepth[i] =D; - if(V[i].empty ())return; - for(intj=0; J<v[i].size (); ++j) - { -DFS (V[i][j], d+1); -p[cnt++] =i; in } - } to + voidRMQ () - { the for(intI=0; i<4*MAXN; ++i) pre_cal[i][0] =i; * for(intj=1; (1<< (J-1)) <4*MAXN; ++j) $ for(intI=0; i+ (1<< (J-1)) <4*MAXN; ++i)Panax NotoginsengPRE_CAL[I][J] = depth[p[pre_cal[i][j-1]]]<depth[p[pre_cal[i+ (1<< (J-1))][j-1]]]?pre_cal[i][j-1]:p re_cal[i+ (1<< (J-1))][j-1]; - } the + stringLcaintAintb) A { the intk = Floor (log (b-a+1)/log (2)); + intx = pre_cal[a][k], y = pre_cal[b-(1<<K) +1][k]; - returnDepth[p[x]]<depth[p[y]]?Name[p[x]]:name[p[y]]; $ } $ - voidInit () - { theCNT =0; - mp.clear ();Wuyi for(intI=0; i<2*MAXN; ++i) v[i].clear (); the } - Wu intMain () - { About stringname1, name2; $ while(cin>>N) - { - init (); - while(n--) A { +Cin>>name1>>name2; the if(Mp.find (name1) = =mp.end ()) - { $MP[NAME1] =CNT; thename[cnt++] =name1; the } the if(Mp.find (name2) = =mp.end ()) the { -Mp[name2] =CNT; inname[cnt++] =name2; the } the V[mp[name1]].push_back (mp[name2]); About } theCNT =0; theDfs0,0); the RMQ (); +Cin>>m; - while(m--) the {BayiCin>>name1>>name2; the intA = mp[name1], B =mp[name2]; thecout<< (Pos[a]<pos[b]?lca (Pos[a], pos[b]): LCA (Pos[b], pos[a)) <<Endl; - } - } the the return 0; the}
Title Link: http://hihocoder.com/problemset/problem/1069
hihocoder1069 recent public ancestor • Three (LCA online algorithm--dfs+rmq-st)