tarjan,树剖,倍增求lca

1.tarjan求lca

思想:

void tarjan(int u,int f){
    
    for(int i=---){//枚举边
        if(v==f) continue;
        dfs(v);   //继续搜 
        unionn(v);//合并
        vis[v]=1; //标记 
    } 
    for(int i){// 和u有关的询问 
        if(vis[v]) 
        lca=find(v);
        //若访问过,lca为find(v) 
    }
}

模板代码

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std;

const int N=500500;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;}
int n,m,s,head[N],tot,fa[N];
struct node{int v,next;}e[N<<1];
inline void insert(int u,int v){
    e[++tot]=(node){v,head[u]};head[u]=tot;
    e[++tot]=(node){u,head[v]};head[v]=tot;}
struct nodex{int x,y,lca;}q[N];
vector<int> link[N];bool vis[N];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline void unionn(int x,int y){
    int xx=find(x),yy=find(y);
    if(xx!=yy) fa[yy]=xx;}
inline
void dfs(int u,int f){ for(int i=head[u];i;i=e[i].next){ int v=e[i].v; if(v==f) continue; dfs(v,u); unionn(u,v); vis[v]=1; } for(int i=0;i<link[u].size();i++){ int v=link[u][i]; int k1=q[v].x,k2=q[v].y; if(k1==u&&vis[k2]) q[v].lca=find(k2); else if(k2==u&&vis[k1]) q[v].lca=find(k1); } } int main(){ n=read(),m=read(),s=read(); rep(i,1,n-1){fa[i]=i; int x=read(),y=read();insert(x,y);} rep(i,1,m){q[i].x=read(),q[i].y=read(); link[q[i].x].push_back(i); link[q[i].y].push_back(i);} fa[n]=n;dfs(s,0); rep(i,1,m) printf("%d\n",q[i].lca); return 0; }

2.倍增lca(在线)

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std;

const int N=500500;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;}
int n,m,s,ss,head[N],tot,dep[N],fa[N][25],k;
struct node{int v,next;}e[N<<1];
inline void insert(int u,int v){
    e[++tot]=(node){v,head[u]};head[u]=tot;
    e[++tot]=(node){u,head[v]};head[v]=tot;}
inline void dfs(int u){
    dep[u]=dep[fa[u][0]]+1;
    for(register int i=1;i<=ss;i++)
    fa[u][i]=fa[fa[u][i-1]][i-1];
    
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(v==fa[u][0]) continue;
        fa[v][0]=u;dfs(v);
    }
}
int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    int k=dep[x]-dep[y];
    
    for(register int i=ss;i>=0;i--)
    if(k&(1<<i)) x=fa[x][i];
    
    if(x==y) return x;
    
    for(register int i=ss;i>=0;i--)
    if(fa[x][i]!=fa[y][i])
    x=fa[x][i],y=fa[y][i];
    
    return fa[x][0];}
int main(){
    n=read(),m=read(),s=read();
    
    ss=ceil(log2(n));
    rep(i,1,n-1){
        int x=read(),y=read();
        insert(x,y);}
    
    fa[s][0]=0; dfs(s);
    
    rep(i,1,m){
        int a=read(),b=read();
        printf("%d\n",lca(a,b));}
    
    return 0;
}

类似模板 s=ceil(log2(n));  bzoj 1787紧急集合

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define dec(i,x,y) for(register int i=x;i>=y;i--)
#define ll long long
using namespace std;
const int N=500050;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;}
int fa[N][20],head[N],tot,dep[N],s;
struct node{int v,next;}e[N<<1];
void insert(int u,int v){
    e[++tot]=(node){v,head[u]};head[u]=tot;
    e[++tot]=(node){u,head[v]};head[v]=tot;}
int n,m,x,y,z;
void dfs(int u){
    dep[u]=dep[fa[u][0]]+1;
    for(int i=1;i<=s;i++)
    fa[u][i]=fa[fa[u][i-1]][i-1];
    
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(v==fa[u][0]) continue;
        fa[v][0]=u;dfs(v);}
}
int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    int k=dep[x]-dep[y];
    
    for(int i=s;i>=0;i--)
    if(k&(1<<i)) x=fa[x][i];
    
    if(x==y) return x;
    
    for(int i=s;i>=0;i--)
    if(fa[x][i]!=fa[y][i])
    x=fa[x][i],y=fa[y][i];
    
    return fa[x][0];}
int main(){
    n=read();m=read();
    s=ceil(log2(n));
    rep(i,1,n-1){
        x=read();y=read();insert(x,y);}
    dfs(1);
    rep(i,1,m){
        x=read();y=read();z=read();
        int xx=lca(x,y),yy=lca(y,z),zz=lca(z,x);
        if(xx==yy)printf("%d ",zz);
        else if(xx==zz) printf("%d ",yy);
        else if(yy==zz) printf("%d ",xx);
        printf("%d\n",dep[x]+dep[y]+dep[z]-dep[xx]-dep[yy]-dep[zz]);}
    return 0;
}

3.树剖(在线)

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std;

const int N=500500;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;}
int n,m,s,head[N],tot;
struct node{int v,next;}e[N<<1];
inline void insert(int u,int v){
    e[++tot]=(node){v,head[u]};head[u]=tot;
    e[++tot]=(node){u,head[v]};head[v]=tot;}

int son[N],fa[N],dep[N],siz[N],top[N];

inline void dfs1(int u ,int f){
    fa[u]=f;siz[u]=1;dep[u]=dep[f]+1;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(v==f) continue;
        dfs1(v,u);siz[u]+=siz[v];
        if(siz[son[u]]<siz[v]) son[u]=v;
    }
}
inline void dfs2(int u,int tp){
    top[u]=tp;
    if(!son[u]) return;
    dfs2(son[u],tp);
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(!top[v]) dfs2(v,v);} 
}
int lca(int x,int y){
    int fx=top[x],fy=top[y];
    while(fx!=fy){
        if(dep[fx]<dep[fy]) swap(fx,fy),swap(x,y);
        x=fa[fx],fx=top[x];}
    return dep[x]<dep[y]?x:y;}
int main(){
    n=read(),m=read(),s=read();
    rep(i,1,n-1){
        int x=read(),y=read();
        insert(x,y);}
    dfs1(s,0);dfs2(s,s);
    rep(i,1,m){
        int a=read(),b=read();
        printf("%d\n",lca(a,b));}
    return 0;
}

 

posted @ 2018-08-30 15:53  ASDIC减除  阅读(192)  评论(0编辑  收藏  举报