zoukankan      html  css  js  c++  java
  • 模板——LCA

    继续存模板。。

    倍增版:

    #include<stdio.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 500000+1;
    int fa[MAXN][21];int deep[MAXN];int n,m,s;
    
    inline void swap(int &a,int &b){
        int t=a;
        a=b;
        b=t;
    }
    
    struct node{
        int v,nxt;
    }e[MAXN*2];int head[MAXN];int cnt=0;
    
    inline void add(int u,int v){e[++cnt].v = v;e[cnt].nxt = head[u];head[u] = cnt;}
    
    inline void bfs(int s,int dad){
        deep[s]=deep[dad]+1;
        fa[s][0]=dad;
        
        for(ll i=1;(1<<i)<=deep[s];++i){
            fa[s][i] = fa[fa[s][i-1]][i-1];
        }
        
        for(ll i=head[s];i;i=e[i].nxt){
            if(e[i].v ^ dad) bfs(e[i].v , s);
        }
    }
    
    inline int lca(int x,int y){
        ll i , j;
        if(deep[x] < deep[y]) swap(x,y);
        
        for(i = 0 ;(1<<i) <= deep[x] ;++i);
        i--;
        
        for(j=i;j>=0;--j)
            if(deep[x] - (1<<j) >= deep[y]) x = fa[x][j];
        if(x == y) return x;
        
        for(j=i;j>=0;--j){
            if(fa[x][j] ^ fa[y][j]){
                x = fa[x][j];y=fa[y][j];
            }
        }
        return fa[x][0];
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&s);
        for(int i=1;i<=n-1;++i){
            int x,y;scanf("%d%d",&x,&y);add(x,y);add(y,x);
        }
        bfs(s,0);
        for(int i=1;i<=m;++i){
            int x,y;scanf("%d%d",&x,&y);
            printf("%d
    ",lca(x,y));
        }
    //	for(int i=1;i<=n;++i) printf("%d ",deep[i]);
        return 0;
    }
    

    tarjan版:

    #include<bits/stdc++.h>
    using namespace std;
    
    const int MAXN = 500000+10;
    
    struct node1{
        int to,next;
        int lca;
    };
    
    node1 e[MAXN*2];
    node1 query[MAXN*2];
    
    int cnt1=0,cnt2=0;
    int head1[MAXN];
    int head2[MAXN];
    int fa[MAXN];
    bool vis[MAXN];
    inline void addedge(int u,int v){
        cnt1++;
        e[cnt1].to = v;
        e[cnt1].next = head1[u];
        head1[u] = cnt1;
    }
    
    inline void addquery(int u,int v){
        cnt2++;
        query[cnt2].to = v;
        query[cnt2].next = head2[u];
        head2[u] = cnt2;
    }
    
    int find(int x){
        return x == fa[x]?x:fa[x] = find(fa[x]);
    }
    
    void tarjan(int x){
        fa[x] = x;
        vis[x] = 1;
        for(int i=head1[x];i;i=e[i].next){
            if(!vis[e[i].to]){
                tarjan(e[i].to);
                fa[e[i].to] = x;
            }
        }
        
        for(int i=head2[x];i;i=query[i].next){
            if(vis[query[i].to]){
                query[i].lca = find(query[i].to);
                if(i%2)
                    query[i+1].lca=query[i].lca;
                else
                    query[i-1].lca=query[i].lca;
            }
        }
    }
    
    int main(){
        int n,q,root;
        scanf("%d%d%d",&n,&q,&root);
        
        for(int i=1;i<n;++i){
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
        
        for(int i=1;i<=q;++i){
            int u,v;
            scanf("%d%d",&u,&v);
            addquery(u,v);
            addquery(v,u);
        }
        
        tarjan(root);
        for(int i=1;i<=q;++i){
            printf("%d
    ",query[i*2].lca);
        }
        return 0;
    }
    

    RMQ版:

    #include<bits/stdc++.h>
    using namespace std;
    const int M=500005;
    struct node{
        int to,next;
    }e[M<<1];
    int k=0,head[M<<1];
    void add(int u,int v)
    {
        e[++k].to=v;
        e[k].next=head[u];
        head[u]=k;
    }
    bool vis[M];
    int cnt,n,m,s,first[M],d[M<<1],pos[M<<1],f[M<<1][21];
    void RMQ()
    {
        for(int i=1;i<=cnt;++i) f[i][0]=i;
        for(int j=1;j<=20;++j)
            for(int i=1;i+(1<<j)-1<=cnt;++i)
                    if(d[f[i][j-1]]<d[f[i+(1<<j-1)][j-1]])
                        f[i][j]=f[i][j-1];
                    else
                        f[i][j]=f[i+(1<<(j-1))][j-1];
    }
    int find(int l,int r)
    {
        int fl=first[l],fr=first[r];
        if(fl>fr) swap(fl,fr);
        int x=log(fr-fl+1.0)/log(2.0);
        if(d[f[fl][x]]<d[f[fr-(1<<x)+1][x]])
            return pos[f[fl][x]];
        else
            return pos[f[fr-(1<<x)+1][x]];
    }
    void dfs(int u,int deep)
    {
        vis[u]=1;
        pos[++cnt]=u;
        d[cnt]=deep;
        first[u]=cnt;
        for(int i=head[u];i^(-1);i=e[i].next)
            if(!vis[e[i].to]){
                dfs(e[i].to,deep+1);
                d[++cnt]=deep;
                pos[cnt]=u;
            }
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&s);
        memset(head,-1,sizeof head);
        for(int i=1;i<n;++i)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        dfs(s,1);
        RMQ();
        for(int i=1;i<=m;++i)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%d
    ",find(a,b));
        }
    }
    

    树链剖分 & 线段树版:

    #include <cstdio>
    #define N 100005
    #define LL long long
    #define Rei register int
    
    inline int read(){
        int _=0;char c=getchar();
        while(c>'9'||c<'0')c=getchar();
        while(c>='0'&&c<='9')_=_*10+c-48,c=getchar();return _;
    }
    
    namespace Segement_Tree{
    #define tl (id<<1)
    #define tr (id<<1|1)
    #define mid (l+r>>1)
    #define lson tl,l,mid
    #define rson tr,mid+1,r
        LL sum[N<<2],lazy[N<<2];
        inline void pushup(int id){sum[id]=sum[tl]+sum[tr];}
        inline void build(int id,int l,int r){
            if(l==r){sum[id]=read();return;}
            build(lson);build(rson);pushup(id);
        }
        inline void pushdown(int id,int l,int r){
            if(!lazy[id]) return ;
            int ls=tl,rs=tr;
            lazy[ls]+=lazy[id];
            lazy[rs]+=lazy[id];
            sum[rs]+=lazy[id]*(r-mid);
            sum[ls]+=lazy[id]*(mid-l+1);
            lazy[id]=0;return ;
        }
        inline void update(int id,int l,int r,int ll,int rr,LL v){
            if(ll<=l&&r<=rr){
                sum[id]+=(r-l+1)*v;
                lazy[id]+=v;return;
            }
            pushdown(id,l,r);
            if(rr<=mid)update(lson,ll,rr,v);
            else if(ll>mid)update(rson,ll,rr,v);
            else update(lson,ll,rr,v),update(rson,ll,rr,v);
            pushup(id);
        }
        inline LL Query(int id,int l,int r,int ll,int rr){
            if(ll<=l&&r<=rr)return sum[id];
            pushdown(id,l,r);
            if(rr<=mid)return Query(lson,ll,rr);
            else if(ll>mid)return Query(rson,ll,rr);
            else return Query(lson,ll,rr)+Query(rson,ll,rr);
        }
    #undef tl
    #undef tr
    #undef mid
    #undef lson
    #undef rson
    }
    
    using Segement_Tree::build;
    using Segement_Tree::Query;
    using Segement_Tree::update;
    
    struct edge{
        int to,nxt;
    }e[N<<1];
    int tot,head[N];
    
    inline void addedge(const Rei&u,const Rei&v){
        e[++tot].to=v;e[tot].nxt=head[u];head[u]=tot;
        e[++tot].to=u;e[tot].nxt=head[v];head[v]=tot;
    }
    
    namespace Tree_pow{
        int top[N],tpos[N],cnt;
        int sz[N],wson[N],fa[N],dep[N];
        inline void dfs(const Rei&u){
            tpos[u]=++cnt;top[u]=u;sz[u]=1;
            for(int i=head[u];i;i=e[i].nxt){
                int v=e[i].to;
                if(v==fa[u])continue;
                dep[v]=dep[fa[v]=u]+1;
                dfs(v);u;sz[u]+=sz[v];
                if(sz[v]>sz[wson[u]])wson[u]=v;
            }
            if(wson[u]) top[wson[u]]=u;
        }
        inline int find(Rei x){return x==top[x]?x:top[x]=find(top[x]);}
        inline int LCA(Rei x,Rei y){
            while(find(x)!=find(y))
                dep[top[x]]<dep[top[y]]
                ?y=fa[top[y]]:x=fa[top[x]];
            return dep[x]<dep[y]?x:y;
        }
    }
    
    using Tree_pow::dfs;
    using Tree_pow::LCA;
    
    int main(){;}
    
  • 相关阅读:
    combo参数配置_手册
    mysql服务器辅助选项
    CentOS中操作
    Linux PHP增加JSON支持及如何使用JSON
    linux服务器命令
    linux中的工具
    linux文件夹操作(及模糊搜索)
    治疗肾结石
    其他书籍
    如何定位到div滚动条的最底端
  • 原文地址:https://www.cnblogs.com/lajioj/p/9480634.html
Copyright © 2011-2022 走看看