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; }