Tree split and multiplied demand chain LCA

Tree split and multiplied demand chain \ (the LCA \)

First of all I want to Tucao spicy base power supply situation room, before I wrote one morning, almost completed when a sudden power outage, then \ (GG \) has become a conveyor chain split
second, I did not discrimination \ (tarjan LCA \)

1. multiplication seeking \ (the LCA \)

One way to understand the relatively simple, but slightly slower

What is the multiplier?

Each number can be split into several times and two integer, we can identify each digit is integer times of which of the two synthetic
example, \ (14 {10} = _ = 1000 1110_2 _2 100 + 10 + _2 _2 = 8 _ 4 _ + {10} + {10} {10} _ 2 \)
so if we want to count a length of the minimum section XIV, we can count the first eight to the minimum number of statistical again after four, then after two statistics.
We can use the \ (f [i] [j ] \) represents the \ (I \) onward \ (2 ^ j \) the minimum length
to the code Ningkang Kang

for( int i = 1; i <= 23; i++ ){
        for( rint j = 1; j <= n; j++ ){
            //a[i][j]存的是i往后2的j次长度的区间的右节点是哪儿
            f[i][j] = min( f[i][j - 1], f[a[i][j - 1]][j - 1] );
        }
    }

Below this thing is what does it mean

f[i][j - 1], f[a[i][j - 1]][j - 1]

\ (2 ^ j = 2 ^ {j-1} + 2 ^ {j - 1} \) For example, \ (2 ^ 4 = 2 + 2 ^ 3 ^ 3 \)

Doubling the tree

To the chain root node do multiplying at each leaf node
picture presentation Kazakhstan(If you open my blog you will find I can not tell if this will only draw konjac

Obviously it should be more ???
We beg \ (LCA \) before \ (dfs \) again, the statistics of each leaf node \ (f [i] [1] \) (ie parent) and \ (DEP [i] \) ( the depth of the node is located, a predetermined depth of the root node). Then run again doubled, each leaf node of the pre-up \ (2 ^ i \) th ancestors who.

Then multiply seeking \ (LCA \) , we can look at whether the two points at the same depth, the point is not, then put up a relatively low walk, walk until the same depth. Note To enumerate when descending jump, to Ningkang Kang code rather then the above \ (14 \) that bring in examples from \ (1 \) to \ (20 \) to enumerate all of a sudden understood

inline int lca( int x, int y ){
    if( dep[x] < dep[y] ) swap( x, y );
    for( rint i = 20; i >= 0; i-- ){
        if( dep[f[x][i]] >= dep[y] ) x = f[x][i];
    }
    if( x == y ) return x;
    for( rint i = 20; i >= 0; i-- ){
        if( f[x][i] == f[y][i] ) continue; //如果跳的一样的话就可能是LCA或者是LCA的祖先,所以先跳到最后一个不一样的,再往上跳一个
        else x = f[x][i], y = f[y][i];
    }
    return f[x][0];
}

\ (AC \) Code

#include<bits/stdc++.h>
using namespace std;
#define rint register int
int n, m, s, cnt, dep[500005], f[500005][23], head[500005];
struct edge{
    int to, nxt;
}a[500005<<1];
inline int read( void ){
    int re = 0, f = 1;
    char ch = getchar();
    while( ch > '9' || ch < '0' ){
        if( ch == '-' ) f = -1;
        ch = getchar();
    }
    while( ch >= '0' && ch <= '9' ){
        re = re * 10 + ch - '0';
        ch = getchar();
    }
    return re * f;
}
inline void addedge( int x, int y ){
    a[++cnt].to = y;
    a[cnt].nxt = head[x];
    head[x] = cnt; 
}
inline void dfs( int x, int fa ){
    dep[x] = dep[fa] + 1;
    f[x][0] = fa;   
    for( rint i = 1; ( 1 << i ) <= dep[x]; i++ ){
        f[x][i] = f[f[x][i - 1]][i - 1];
    }
    for( rint i = head[x]; i; i = a[i].nxt ){
        int v = a[i].to;
        if( v == fa ) continue;
        dfs( v, x ); 
    }
    return ;
}
inline int lca( int x, int y ){
    if( dep[x] < dep[y] ) swap( x, y );
    for( rint i = 20; i >= 0; i-- ){
        if( dep[f[x][i]] >= dep[y] ) x = f[x][i];
    }
    if( x == y ) return x;
    for( rint i = 20; i >= 0; i-- ){
        if( f[x][i] == f[y][i] ) continue;
        else x = f[x][i], y = f[y][i];
    }
    return f[x][0];
}
int main( void ){
    n = read(); m = read(); s = read();
    for( rint i = 1; i <= n - 1; i++ ){
        int x, y; x = read(); y = read();
        addedge( x, y ); addedge( y, x );
    }   
    dfs( s, 0 );
    int u, v;
    for( rint i = 1; i <= m; i++ ){
        u = read(); v = read();
        cout << lca( u ,v ) << endl;    
    }
    return 0;
}

Tree chain split

Tree chain split split actually a good variety of methods, but here only the severity gon

meaning

A node can have a heavy son.
Chain: Continuous heavy / light constituting a side chain. (From FIG \ (1 \) to \ (14 \), i.e., a heavy chain)
\ (DEP [I] \) : \ (I \) depth of the node, the root node of a predetermined depth \ (1 \) .
\ (FA [i] \) : \ (i \) parent node.
\ (Son [I] \) : \ (I \) heavy son nodes.
\ (SIZ [I] \) : In \ (I \) size of the root node of the subtree.
\ (Top [I] \) : \ (I \) root where chain. (FIG from \ (1 \) to \ (14 \) root chain is \ (1 \) )
multiple edges: In \ (I \) son node (SIZ \) \ eldest son to \ ( I \) connected edges, i.e. the thick edge (also called the son son weight).
Light side: the weight of the outer edge of the other sides.

step

First \ (dfs \) again, determined \ (DEP \) , \ (FA \) , \ (Son \) , \ (SIZ \) , easy to implement, the code to Ningkang

inline void dfs1( int now, int father, int de ){
    siz[now] = 1; fa[now] = father; dep[now] = de;
    int maxn = -1;
    for( rint i = 0; i < vec[now].size(); i++ ){
        int v = vec[now][i];
        if( v == father ) continue ;
        dfs1( v, now, de + 1 );
        siz[now] += siz[v];
        if( siz[v] > maxn ){
            maxn = siz[v];
            son[now] = v;
        }
    }
}

Then \ (dfs \) again, the processing of each point \ (Top \) , which is the apex where the chain, which is the apex of the light chain of its own.
Code to Ning Kangkang

inline void dfs2( int now, int topf ){
    top[now] = topf;
    if( !son[now] ) return ;
    dfs2( son[now], topf );
    for( rint i = 0; i < vec[now].size(); i++ ){
        int v = vec[now][i];
        if( v == fa[now] || v == son[now] ) continue;
        dfs2( v, v );
    }
}

If it's a point to jump \ (lca \) , it will jump to its \ (lca \) where the chain (nonsense ......

So we have to determine whether or not to have found \ (LCA \) , it just depends on the current points \ (xy \) is on the same chain, in fact, is to look at two points \ (top \) are equal, if not equal then we let the depth of the large dot one-time dance through an entire heavy chain, and then jump step onto the other heavy chain, and then repeat the above comparison \ (Top \) , jump process heavy chain

We can find some non-leaf nodes on a heavy chain, so we dance through a one-time heavy chain, jump step, it will jump on the other heavy chain, so look for \ (lca \) complexity is less than \ (logn \) of

Code to Ning Kangkang

inline int lca( int x, int y ){
    while( top[x] != top[y] ){
        if( dep[top[x]] < dep[top[y]] ) swap( x, y );
        x = fa[top[x]];
    }
    if( dep[x] > dep[y] ) return y;
    return x;
}

All Code:

#include<bits/stdc++.h>
using namespace std;
#define rint register int
int T, n, m;
int son[1000010], fa[1000010], siz[1000010], dep[1000010], top[1000010];
vector< int > vec[1000010];
inline int read( void ){
    int re = 0, f = 1; char ch = getchar();
    while( ch > '9' || ch < '0' ){
        if( ch == '-' ) f = -1;
        ch = getchar();
    }
    while( ch >= '0' && ch <= '9' ){
        re = re * 10 + ch - '0';
        ch = getchar();
    }
    return re * f;
}
inline void dfs1( int now, int father, int de ){
    siz[now] = 1; fa[now] = father; dep[now] = de;
    int maxn = -1;
    for( rint i = 0; i < vec[now].size(); i++ ){
        int v = vec[now][i];
        if( v == father ) continue ;
        dfs1( v, now, de + 1 );
        siz[now] += siz[v];
        if( siz[v] > maxn ){
            maxn = siz[v];
            son[now] = v;
        }
    }
}
inline void dfs2( int now, int topf ){
    top[now] = topf;
    if( !son[now] ) return ;
    dfs2( son[now], topf );
    for( rint i = 0; i < vec[now].size(); i++ ){
        int v = vec[now][i];
        if( v == fa[now] || v == son[now] ) continue;
        dfs2( v, v );
    }
}
inline int lca( int x, int y ){
    while( top[x] != top[y] ){
        if( dep[top[x]] < dep[top[y]] ) swap( x, y );
        x = fa[top[x]];
    }
    if( dep[x] > dep[y] ) return y;
    return x;
}
int main( void ){
    n = read(); m = read();
    for( rint i = 1; i < n; i++ ){
        int u, v; u = read(); v = read();
        vec[u].push_back( v ); 
        vec[v].push_back( u );
    }
    dfs1( 1, 1, 1 );
    dfs2( 1, 1 );
    for( rint i = 1; i <= m; i++ ){
        int x, y; x = read(); y = read(); 
        printf( "%d\n", lca( x, y ) );
    }    
    return 0;
}

If the shortest distance between two points in claim tree, can find \ (LCA \)
\ (DIS DEP = [X] DEP + [Y] - 2 * LCA \)

Guess you like

Origin www.cnblogs.com/with6676/p/11795224.html