模板——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\n",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\n",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\n",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(){;}

猜你喜欢

转载自www.cnblogs.com/lajioj/p/9480634.html