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(){;}
    
  • 相关阅读:
    DC中为什么要用Uniquify?
    hdu 1596 find the safest road
    hdu2112 HDU Today
    hdu 2066 一个人的旅行
    poj 3026 Borg Maze
    poj 1979 Red and Black
    poj 1321 棋盘问题
    hdu 1010 Tempter of the Bone
    hdu 4861 Couple doubi
    codeforces584B Kolya and Tanya
  • 原文地址:https://www.cnblogs.com/lajioj/p/9480634.html
Copyright © 2011-2022 走看看