Reference Link: http://dongxicheng.org/structure/union-find-set/author Dong Algorithm Introduction
The definition of LCA (Least Common ancestors) is such that, given 2 points, it is the public ancestor closest to them that is the deepest (or farthest from the root). This problem if you think carefully, nor algorithm is particularly difficult a problem, the simplest way is to start from 2 points in turn, to the Father node to look for, if there are 2 fathers node is the same, the father is this 2 points of the recent public ancestor. Of course, this is the simplest and easiest way to think about it. So the efficiency of the algorithm described in this article is certainly much better than this. LCA algorithm is divided into offline algorithm and online algorithm 2 kinds. Then some people will think, what is the difference between them, the online algorithm, as the name implies, is the request data input one, then output a result, and then input a request query, in the output, online meaning, very good understanding. The offline algorithm refers to the one-time input of all request query conditions, and then need to output all the results at the end of the algorithm execution. Because the more commonly said is the LCA offline algorithm, so today I write is the LCA of the offline algorithm for the solution. algorithm principle
The off-line algorithm of LCA uses the Tarjan algorithm, I have not contacted before the Tarjan algorithm, checked, is used to seek the strong connected component of the graph. It uses the knowledge of the set and DFS depth-first algorithms. DFS depth-First algorithm everyone knows what's going on, and it's not a lot of people who have heard about it. OK, let's introduce some concepts and operations of the set. and check Set
And check the operation of the main there are 2, one is Findset (), used to find the ancestors of the node, the ancestor is characterized by the ancestor of his father equals himself, with this as the key to determine the conditions, illustrated as follows:
Another operation is unionset (int a, int b), merging the collection operations, identifying the ancestors of 2 nodes, and pointing the ancestor of one of the nodes to the other node. This is illustrated below:
and check the relevant implementation of the code in the following code implementation will be given, please pay attention to observation. algorithm Process
The execution of the algorithm is based on the DFS depth-first traversal, each time a node is traversed, it will re-merge this point with the Father node, which is the algorithm of the more ingenious operation. The execution of the algorithm is very high, as long as the traversal of the whole tree, you can get all the results, all his time complexity is O (n + q), n is the total number of nodes, Q is the number of queries, the linear level. The pseudo code of the algorithm is as follows:
[Java] View plain copy print? LCA (u) { Make-set (U) ancestor[find-set (U)] =u for every child of U v { LCA (v) Union (U) Ancestor[find-set (u)]=u } checked[u]=true for each (u,v) belongs to q { if checked[v]=true then { the nearest public ancestor to answer U and V is ancestor[find-set (v)] } } }
When I realized it, I omitted the Ancestor[find-set (u)] = u, which I think is already contained in the Union, which I feel is quite puzzling. The complete implementation of the algorithm is given below.
Implementation of the algorithm
Test point Data datafile:
[Java] view plain copy print? 1 2 3 4 5 6 7 8 9 10 Query request data queryfile:
To accurately test the entire process of traversal, I enumerate all the points that make up the query pair, that is to say, there are 9 + 8 + 7 + .... + 1 = 45 kinds of possible.
[Java] view plain copy print? 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1 10 2 3 2 4 2 5 2 6