Jinan training and content, people head bald (two teacher had to say it twice before I barely get to know a little bit)
First look:
LCA meaning
Least Common Ancestors
LCA is the most recent common ancestor, as to its meaning, I think the examples will look to write more clearly, see:
Well, to understand its meaning, we can easily think of simple arithmetic:
Ask (x, y) of the common ancestor, ancestors may first enumerate all of x,
stored in an array Anc [] in. Then the same method to enumerate all ancestors y direction of
the first, when the first time found to have an ancestor of y k appears in Anc [], the output
k, the algorithm ends.
In this case, each query complexity is
O (N)
(TLE warning oh)
Then the other way to do that, see, describe two here,
the trees doubled
, and
tree-chain split (will write a blog in the next)
Doubling the tree algorithm
main idea:
- So that F [x] [n] is represented by x 2 ^ n whose ancestor class Yes.
- Therefore: F [x] [n] = F [F [x] [n - 1]] [n - 1].
- For two points x, y., Seeking their LCA
- First x, y mentioned the same height . (Multiplication facilitate upward)
- N descending enumeration. (From high to low transition)
- Query F [x] [n], F [y] [n] is not equal (multiplication ancestor after comparison, to prevent false positives )
- If so too n explanation, the n piecemeal point ( common ancestor ancestors must be their common ancestor )
- Not, then do not explain n, can be x, y-shift. (This is easy to understand it)
Principle, as shown below (images from
the teacher's PPT
)
(which actually should have a moving map but I do not know how to pass a motion picture)
:
Yet understand the idea, the idea can still understand it, then we look at the code, understand the code base will be able to write!
(But before I always do not understand the code it wants, thinking the code is not going to know everything, I really little trash oh)
#include <cstdio> #include <the iostream> #include <the cmath> the using namespace STD; const int MAXN = 500 005 ; const int Maxe = 1000005 ; int n-, m, the root; struct Line { int from , to; Line () { } // empty constructor P Line; Line ( int A, int B) { // constructors L = Line Line (1,2); from = A; to = B; } } Edge [Maxe]; // above It is to create a tree intLast [MAXN], _ Next [Maxe], E; // Last [x] x represented as a starting point of the last edge (number) // -next [i] denotes the i-th starting point on the same side of an edge ( numbering) void add_edge member ( int X, int Y) { edge [ ++ E] = Line (X, Y); -next [E] = Last [X]; Last [X] = E; } // save sides int FA [MAXN] [ 35 ], Dep [MAXN]; void DFS ( int x, int FA) { int I, K, Y; FA [x] [ 0 ] = FA; // parent node of the current node x FA Dep [x] = Dep [Fa [ x] [0 ]] + 1 ; // depth is the depth x +1 its parent node // record the depth of the current node K = ceil (log (Dep [x]) / log ( 2 )); // ceil function upward rounding // X doubling up the upper limit for (I = . 1 ; I <= K; I ++) Fa of the [X] [I] = Fa of the [Fa of the [X] [I- . 1 ]] [I- . 1 ]; / / multiplication calculation ancestors recorded for ( int I = Last [x]; I; I = -next [I]) // enumeration adjacent sides and x { int V = edge [I] .to; IF (V! = FA) DFS (V, X); } } int the LCA (int X, int Y) { int I, K, S; S = ceil (log (n-) / log ( 2 )); // the maximum possible limit tree multiplier IF (Dep [X] <Dep [Y]) the swap (x, y); // exchange the values of x and y //////////// / x k layers go up, so that x and y in the same layer //////// / / K = Dep [X] - Dep [Y]; for (I = 0 ; I <= S; I ++ ) IF (K & ( . 1 << I)) X = Fa of the [X] [I]; IF (X the y-==) return the X-; // when x == y, x is the most recent common ancestor /////////////////////////////////////////////////// s=ceil(log(Dep[x])/log(2)); //计算向上倍增的上限 for(i=s;i>=0;i--) if(Fa[x][i]!=Fa[y][i]){ x=Fa[x][i]; y=Fa[y][i]; } return Fa[x][0]; } int main() { int i,j,k; cin>>n>>m>>root; for(i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); add_edge member (X, Y); add_edge member (Y, X); // it is a tree, i.e. undirected graph, so keep the two sides } DFS (the root, 0 ); // preprocessing for (I = . 1 ; I <= m; I ++ ) { int X, Y; Scanf ( " % D% D " , & X, & Y); the printf ( " % D \ n- " , the LCA (X, Y)); } }
OK it?
It is recommended that the board go to practice, guiding -> https://www.luogu.org/problem/P3379
(Wow I was able to write the title Blue hey !! gratifying)
First here,
if there are questions please correct me
Thank you for Nursing sensitive 谢观