[A] konjac struggle the LCA (multiplication)

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)); 
    } 
        
}
Code (with comments)  

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 谢观


 

Guess you like

Origin www.cnblogs.com/Phantomhive/p/11552874.html
lca