• P3379 【模板】最近公共祖先(LCA)(树链剖分)版


    #include <bits/stdc++.h>
    #define read read()
    #define up(i,l,r) for(register int i = (l);i <= (r);i++)
    #define down(i,l,r) for(register int i = (l);i >= (r);i--)
    #define traversal_vedge(i) for(register int i = head[u]; i ;i = e[i].nxt)
    #define ll long long
    using namespace std;
    int read
    {
        int x = 0, f = 1; char ch = getchar();
        while(ch < 48 || ch > 57) {if(ch == '-')f = -1; ch = getchar();}
        while(ch >=48 && ch <=57) {x = 10 * x + ch - 48;ch = getchar();}
        return x * f; 
    }
    
    int n,m,s;
    const int N = 500005;
    int dep[N],fa[N],size[N],top[N];
    
    struct edge{
        int v,nxt;
    }e[N<<1];int cnt,head[N];
    void add(int u,int v){
        e[++cnt] = (edge){v,head[u]};
        head[u] = cnt;
    }
    
    void readdata()
    {
        n = read; m = read; s = read;
        up(i,1,n-1)
        {
            int u = read,v = read;
            add(u,v);
            add(v,u);
        }
    }
    //-----------------------------------------------------------------------
    void dfs(int u)
    {
        dep[u] = dep[fa[u]] + 1;
        size[u] = 1;
        top[u] = u;
        //debug 未写 top[u] = u; 
        int heavyson_id = 0,heavyson_size = 0;
        traversal_vedge(i)
        {
            int v = e[i].v;
            if(v == fa[u]) continue;
            fa[v] = u; //top[v] = u;
             
            //debug 不写top[v] = u;
            dfs(v);
            size[u] += size[v];
            //heavyson = max(heavyson,size[v]);
            if(size[v] > heavyson_size) heavyson_id = v,heavyson_size = size[v]; 
        }
        if(heavyson_id) top[heavyson_id] = u;//debug heavyson_id -> u;
        //有重儿子才更新top[] 
        //dfs后,top[]只相当于重链上的fa[] 
        
        //调用find(u)过后,从u到链首的所有top[]才指向链首; 
    }
    
    int find(int u)
    {
        if(u == top[u]) return u;
        top[u] = find(top[u]);//debug top[u] -> u
        return top[u];
        //逆向搜索,并修改值; 
    }
    
    int lca(int x,int y)
    {
        if(find(x) != find(y)) //如果不在一条链上
        //**一条链:重链为一条链,轻链单独一条边为一条链;
        {
            if(dep[top[x]] > dep[top[y]]) return lca(fa[top[x]] , y);//debug fa[top[x]] -> fa[dep[top[x]]];
            else return lca(x , fa[top[y]]);
        }
        return dep[x] > dep[y] ? y : x;
    }
    
    void work()
    {
        dfs(s);
        while(m--)
        {
            int a = read,b = read;
            printf("%d
    ",lca(a,b)); 
        }
    }
    
    int main()
    {
        freopen("input.txt","r",stdin);
        readdata();
        work();
        return 0;
    } 

    总结:

    树链剖分版的LCA的dfs1稍有不同,不需要用数组记录每个点的重儿子;

    树链剖分维护7个数组,树链剖分——LCA维护4个数组(fa[],dep[],size[],top[])son[]简化成heavyson_id

  • 相关阅读:
    [BZOJ 2653]middle
    svn提交错误
    查看当前功能地址
    后台纯代码--短信验证
    图片验证码~~~之后台生成随机数
    小程序之~~登录后台代码
    小程序登录过程简介
    小程序之~微信登录后台代码
    小程序之~~基于微信登录,后台代码
    小程序之~~短信验证
  • 原文地址:https://www.cnblogs.com/mzg1805/p/10415474.html
Copyright © 2020-2023  润新知