Detailed tree multiplier seeking LCA

LCA (least common ancestors) most recent common ancestor

It refers to a rooted tree, if both nodes z x ancestors, is the ancestor of y ( Do not tell me you do not know what is the ancestor ), then z is the node x and y recent common ancestor.

The definition of this.

So how demand LCA?

For simple idea, that is, I want to climb step by step. . Step by step. First the node x and y to the same depth of the whole, then again up to a depth of investigation, only ancestors until BREAK (apparently a while)

However, step by step, it is too slow, so you can not go down to earth

Well, consider jumping to go,

Jumping to go step by step to meet the condition that the number as much as possible and do not skip. Of course, you skip a step by step look down the line ah QWQ

Thus, in the case of these two conditions are satisfied, we have LCA algorithm:

Article step 2 ^ n.

For each step of the jump, we want a two-dimensional array of pre-f (father) f [x] [i], x represents for the current node, jump up 2 ^ i ancestor, in particular, like mathematics, f [x] [0] is the generation ancestor of x. So we use a pre-dfs to solve the f array. Later we will mention;

F array of processed, it is very simple.

Input x and y, x represents claim LCA node and the node y, then we begin seeking LCA:

For different heights x and y, we put them pulled a high degree, the same can not go step by step, but also used f array.

Here we need to understand in advance a theorem: For any non-zero integer, we can use his power of two that out. I.e. such as: 11 = 2 ^ 3 + 2 ^ 1 + 2 ^ 0. This idea is not necessary to prove, as if each number can be used as a binary representation.

Then say: when the x and y to get the same level, we have to do first is to set the depth dep dep depth x is greater than y, if dep [y]> dep [x ], then exchange them. The reason is that if the exchange does not, then we need to determine both cases, and two if almost the same code. . ( Mess also account for memory )

Then a determination if (dep [f [x] [i]]> = dep [y]) x = f [x] [i]; ( x case depth is greater than y), used here for the outer loop enumeration i, but i must be large to small! . why?

Amway story ( actually not ): a glass bottle, put a few stones, full to the brim. Full? No. I have installed some sand, full to the brim. Full? No. And finally filled with water , filled to the brim. And finally full.

So, analogous to the depth of the distance x and y, the volume of the bottle is the same reason. From the greatest possible power of 2 to find, once able to find close to their i, updated dep [x], until equal. Unlimited approach is similar to the process equal to the final value. If i is equal, and it shows that they are already at the same level of depth.

Compared with the same process to multiply the depth of doubling find common ancestor it is similar, but a little different is that you do not know when they find a common ancestor, so there is no upper limit to find, then let them close as possible. Therefore, the conditions changed this:

if(f[x][i]!=f[y][i])
        {
            x=f[x][i];y=f[y][i];
        }

After execution of this statement, we have successfully let x and y z becomes a node in the left and right son!

Because the son is about the closest, but not equal.

So we just take one look Dad, just find the LCA.

what. . . . . . catch my breath

AC Code:

For the chain of FIG stored understand this point.

 

#include<cstdio>
#include<iostream>
using namespace std;
int n,m,s,num=0,head[1000001],dep[1000001],f[1000001][23];
int a1,a2;
struct edg{
    int next,to;
}edge[1000001];
void edge_add(int u,int v)//链式前向星存图 
{
    num++;
    edge[num].next=head[u];edge[num].to=v;head[u]=num;
    edge[++num].next=head[v];edge[num].to=u;head[v]=num;
}
void dfs(int u,int father)//对应深搜预处理f数组 
{
    dep[u]=dep[father]+1;
    for(int i=1;(1<<i)<=dep[u];i++)
    {
        f[u][i]=f[f[u][i-1]][i-1];
    }
    for(int i=head[u];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==father)Continue ; // bipartite graph is not necessary to determine the parent node 
        F [V] [ 0 ] = U; 
        DFS (V, U); 
    } 
} 
int LCA ( int X, int Y) 
{ 
    IF (DEP [X] < DEP [ y]) the swap (x, y);
     for ( int I = 20 is ; I> = 0 ; i--) // descending enumeration of x and y to make the same layer 
    {
         IF (DEP [F [x] [I]]> DEP = [Y]) X = F [X] [I];
         IF (X == Y) return X; 
    } 
    for ( int I = 20 is ; I> =0 ; i--) // descending enum 
    {
         IF (F [X] [I] = F [Y] [I])! // as close 
        { 
            X = F [X] [I]; Y = F [Y] [I]; 
        } 
    } 
    return F [X] [ 0 ]; // with a random ** output 
}
 int main () { 
    Scanf ( " % D% D% D " , & n-, & m, & S);
     for ( int I = . 1 ; I <n-; I ++ ) 
    { 
        Scanf ( " % D " , & A1); Scanf ( " % D ", & A2); 
        edge_add (A1, A2); // chain deposit side 
    } 
    DFS (S, 0 );
     for ( int I = . 1 ; I <= m; I ++ ) 
    { 
        Scanf ( " % D% D " , A1 &, & A2); 
        the printf ( " % D \ n- " , LCA (A1, A2)); // find two nodes in the LCA 
    } 
}

 

end. .

 

Guess you like

Origin www.cnblogs.com/lbssxz/p/11114819.html