zoukankan      html  css  js  c++  java
  • 模板

    倍增lca
    预处理每个节点的深度,从节点(u)向上跳(2^k(0leq kleq log n))步所能到达的节点编号
    预处理时间复杂度(O(nlog n))
    查询时间复杂度(O(log n))

    const int maxn=40010;
    int depth[maxn],fa[maxn][20];
    
    void dfs(int u,int f){
        fa[u][0]=f;
        for(int i=head[u];~i;i=ne[i]){
            int v=to[i];
            if(v!=f){
                depth[v]=depth[u]+1;
                dfs(v,u);
            }
        }
    }
    
    void lca_init(){
        depth[1]=1;
        dfs(1,0);
        for(int j=1;j<20;j++){
            for(int i=1;i<=n;i++){
                fa[i][j]=fa[fa[i][j-1]][j-1];
            }
        }
    }
    
    int lca(int x,int y){
        if(depth[x]>depth[y]) swap(x,y);
        int d=depth[y]-depth[x];
        for(int i=0;i<20;i++){
            if((1<<i)&d) y=fa[y][i];
        }
        if(x==y) return x;
        for(int i=19;i>=0;i--){
            if(fa[x][i]!=fa[y][i]){
                x=fa[x][i];
                y=fa[y][i];
            }
        }
        return fa[x][0];
    }
    

    模板题:hdu2586 How far away ?
    基于rmq的算法
    按照从根节点开始的(dfs)访问顺序得到顶点序列(vs[maxn]),节点深度(depth[maxn]),每个节点第一次出现在顶点序列中的下标(id[maxn])
    (id[u]leq id[v]),则有:

    [lca(u,v)=vs[id[u]leq ileq id[v]中令depth[i]最小的i] ]

    可以通过(rmq)查询,返回的是下标而不是最值

    const int maxn=10010,maxm=20010;
    int n,st[2*maxn][15],mini[2*maxn],idx[2*maxn][15];
    int vs[2*maxn],depth[2*maxn],id[maxn];
    
    void rmq_init(int n){
        for(int i=1;i<=n;i++){
            st[i][0]=depth[i];
            idx[i][0]=i;
        }
        for(int j=1;(1<<j)<=n;j++){
            for(int i=1;i+(1<<j)-1<=n;i++){
                if(st[i][j-1]<st[i+(1<<(j-1))][j-1]){
                    st[i][j]=st[i][j-1];
                    idx[i][j]=idx[i][j-1];
                }
                else{
                    st[i][j]=st[i+(1<<(j-1))][j-1];
                    idx[i][j]=idx[i+(1<<(j-1))][j-1];
                }
            }
        }
        for(int len=1;len<=n;len++){
            int k=0;
            while((1<<(k+1))<=len) k++;
            mini[len]=k;
        }
    }
    
    int rmq_id(int l,int r){
        int k=mini[r-l+1];
        if(st[l][k]<st[r-(1<<k)+1][k]) return idx[l][k];
        return idx[r-(1<<k)+1][k];
    }
    
    void dfs(int u,int fa,int dep,int& k){
        id[u]=k;
        vs[k]=u;
        depth[k++]=dep;
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i];
            dfs(v,u,dep+1,k);
            vs[k]=u;
            depth[k++]=dep;
        }
    }
    
    void lca_init(int root){
        int k=1;
        dfs(root,-1,0,k);
        rmq_init(2*n-1);
    }
    
    int lca(int u,int v){
        return vs[rmq_id(min(id[u],id[v]),max(id[u],id[v]))];
    }
    
  • 相关阅读:
    把旧表中数据加入到新表中
    mysql字段-创建时间与更新时间
    springboot-maven依赖源
    刚刚下载的IDEA打不开
    matplotlib-实战01
    实战1-数据清理
    python函数(三)
    交换机配置DHCP中继
    python函数(二)
    用事实说话
  • 原文地址:https://www.cnblogs.com/fxq1304/p/13388730.html
Copyright © 2011-2022 走看看