lca问题
1.树链剖分
#include#include #include #define maxn 500001 using namespace std; int n,m,s,cnt,head[maxn],to[maxn<<1],nex[maxn<<1]; int fa[maxn],dep[maxn],id[maxn],a[maxn],top[maxn],siz[maxn],son[maxn]; inline void read(int &x){ char ch=getchar();x=0; while(!isdigit(ch))ch=getchar(); while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} } void addedge(int u,int v){ to[++cnt]=v;nex[cnt]=head[u];head[u]=cnt; } void dfs1(int x,int f){ dep[x]=dep[f]+1;fa[x]=f;siz[x]=1; int maxson=-1; for(int i=head[x];i;i=nex[i]){ int v=to[i]; if(v==f)continue; dfs1(v,x); siz[x]+=siz[v]; if(siz[v]>maxson){son[x]=v;maxson=siz[v];} } } inline void dfs2(int x,int topf){ id[x]=++cnt; a[cnt]=x; top[x]=topf; if(!son[x])return; dfs2(son[x],topf); for(int i=head[x];i;i=nex[i]){ int y=to[i]; if(y==fa[x]||y==son[x])continue; dfs2(y,y); } } int query(int x,int y){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y);//尤其要注意这里是dep[top[x]] =fa[top[x]]; } return dep[x] int main(){ read(n);read(m);read(s); for(int i=1;ix:y; } ){ int u,v;read(u);read(v);addedge(u,v);addedge(v,u); } cnt=0; dfs1(s,s);dfs2(s,s); for(int i=1;i<=m;i++){ int u,v;read(u);read(v);printf("%d\n",query(u,v)); } }
2.tarjan算法
遍历一棵树,不断更新当前节点子节点的父亲。。。具体可看代码,不难
#include#include #include #define maxn 500002 using namespace std; int n,m,s,cnt,ans[maxn],fa[maxn],h[maxn],head[maxn],to[maxn<<1],nex[maxn<<1]; struct data{int v,id,ans,nex;}q[maxn<<1]; bool vis[maxn]; inline void read(int &x){ char ch=getchar();x=0; while(!isdigit(ch))ch=getchar(); while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} } void addedge(int u,int v){ to[++cnt]=v;nex[cnt]=head[u];head[u]=cnt; } void add(int u,int v,int id){ q[++cnt].v=v;q[cnt].id=id;q[cnt].nex=h[u];h[u]=cnt; } int findfa(int x){ if(fa[x]==x)return x;return fa[x]=findfa(fa[x]); } void unio(int x,int y){ int fx=findfa(x),fy=findfa(y); fa[fx]=fy; } void lca(int now,int fa){ for(int i=head[now];i;i=nex[i]){ if(to[i]==fa)continue; lca(to[i],now); unio(to[i],now); } vis[now]=1; for(int i=h[now];i;i=q[i].nex){ if(vis[q[i].v]) ans[q[i].id]=findfa(q[i].v); } } int main(){ read(n);read(m);read(s); for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i ){ int u,v; read(u);read(v); addedge(u,v);addedge(v,u); } cnt=0; for(int i=1;i<=m;i++){ int u,v; read(u);read(v); add(u,v,i);add(v,u,i); } lca(s,0); for(int i=1;i<=m;i++)printf("%d\n",ans[i]); }
3.dfs+倍增
#include
#include
#include
#define maxn 500005
using namespace std;
int n,m,s,head[maxn],ln[500005],st[maxn][22],dep[maxn];
struct data{int v,nxt;}edge[maxn*2];
inline int read(){
char ch=getchar();int k=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch)){k=(k<<1)+(k<<3)+ch-'0';ch=getchar();}
return k;
}
void dfs(int now,int fa){
dep[now]=dep[fa]+1;
st[now][0]=fa;
for(int i=1;(1<dep[y])x=st[x][ln[dep[x]-dep[y]]-1];
if(x==y)return x;
for(int j=ln[dep[x]]-1;j>=0;j--)//
if(st[x][j]!=st[y][j]) x=st[x][j],y=st[y][j];
return st[x][0];
}
int main(){
n=read();m=read();s=read();
for(int i=1;i