树 模板
1145141919810114514191981011451419198101145141919810114514191981011451419198101145141919810114514191981011451419198101145141919810114514191981011451419198101145141919810114514191981011451419198101145141919810114514191981011451419198101145141919810
倍增
int n,m;
vi e[maxn];
int fa[maxn][20],dep[maxn];
void dfs(int u,int pa){
fa[u][0]=pa,dep[u]=dep[pa]+1;
For(i,1,19)fa[u][i]=fa[fa[u][i-1]][i-1];
for(auto v:e[u])if(v!=pa)dfs(v,u);
}
int lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
Rep(i,19,0)if(dep[fa[u][i]]>=dep[v])u=fa[u][i];
if(u==v)return u;
Rep(i,19,0)if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
int dist(int u,int v){return dep[u]+dep[v]-2*dep[lca(u,v)];}
int kth(int u,int k){
For(i,0,19)if(k>>i&1)u=fa[u][i];
return u;
}
int jump(int u,int v){return kth(u,dep[u]-dep[v]-1);}
int go(int u,int v,int k){
int d=dep[lca(u,v)];
return k<=dep[u]-d?kth(u,k):kth(v,dep[v]+dep[u]-2*d-k);
}
struct cir{
int u,r;
cir(int x=0,int y=0):u(x),r(y){}
friend cir operator +(cir a,cir b){
int len=dist(a.u,b.u);
if(a.r+len<=b.r)return b;
if(b.r+len<=a.r)return a;
return cir(go(a.u,b.u,(b.r-a.r+len)/2),(a.r+b.r+len)/2);
}
};
st表
int n,m;
vi e[maxn];
int d[maxn];
void bfs(){
memset(d,63,sizeof d);queue<int>q;
For(i,1,n)if(e[i].size()==1)d[i]=0,q.push(i);
while(q.size()){
int u=q.front();q.pop();
for(auto v:e[u])if(d[v]==inf)d[v]=d[u]+1,q.push(v);
}
}
int fa[maxn],dep[maxn],sz[maxn];
int dfn[maxn],que[maxn],out[maxn],idx;
int st[20][maxn],lg[maxn];
int depmin(int u,int v){return dep[u]<dep[v]?u:v;}
void dfs(int u){
dfn[u]=++idx,que[idx]=u,sz[u]=1;
for(auto v:e[u]){
if(v==fa[u])continue;
fa[v]=u,dep[v]=dep[u]+1;
dfs(v),sz[u]+=sz[v];
}out[u]=idx;
}
void init(){
dfs(1);
For(i,2,n)st[0][i]=fa[que[i]],lg[i]=lg[i>>1]+1;
For(j,1,19)
For(i,1,n-(1<<j)+1)
st[j][i]=depmin(st[j-1][i],st[j-1][i+(1<<(j-1))]);
}
int lca(int u,int v){
if(u==v)return u;
if((u=dfn[u])>(v=dfn[v]))swap(u,v); ++u;
int k=__lg(v-u+1);
return depmin(st[k][u],st[k][v-(1<<k)+1]);
}
int dist(int u,int v){
if(!u||!v)return -((!u)+(!v));
return dep[u]+dep[v]-2*dep[lca(u,v)];
}
struct diam{
int u,v,d;
diam(int x=0,int y=0){u=x,v=y,d=dist(x,y);}
bool operator <(const diam&b)const{return d<b.d;}
void ins(int x){
if(!x)return;
int du=dist(u,x),dv=dist(v,x);
if(du<dv)swap(u,v),swap(du,dv);
if(du>d)v=x,d=du;
}
void operator +=(diam b){ins(b.u),ins(b.v);}
friend diam operator +(diam a,diam b){a+=b;return a;}
friend diam operator *(diam a,diam b){return max(max(diam(a.u,b.u),diam(a.v,b.v)),max(diam(a.u,b.v),diam(a.v,b.u)));}
};
bool dfncmp(int u,int v){return dfn[u]<dfn[v];}
vi G[maxn];
void addg(int u,int v){G[u].pb(v);}
void vtree(vi&o){
int k=o.size();
sort(o.begin(),o.end(),dfncmp);
For(i,1,k-1)o.pb(lca(o[i-1],o[i]));
sort(o.begin(),o.end(),dfncmp),o.erase(unique(o.begin(),o.end()),o.end());
For(i,1,(int)o.size()-1)addg(lca(o[i-1],o[i]),o[i]);
}
树剖
int n,m;
vi e[maxn];
int fa[maxn],son[maxn],sz[maxn],dep[maxn];
int dfn[maxn],out[maxn],top[maxn],que[maxn],idx;
void dfs1(int u){
sz[u]=1;
for(auto v:e[u]){
if(v==fa[u])continue;
fa[v]=u,dep[v]=dep[u]+1,dfs1(v),sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
top[u]=tp,dfn[u]=++idx,que[idx]=u;
if(son[u])dfs2(son[u],tp);
for(auto v:e[u])if(v!=fa[u]&&v!=son[u])dfs2(v,v);
out[u]=idx;
}
int lca(int u,int v){
for(;top[u]!=top[v];u=fa[top[u]])if(dep[top[u]]<dep[top[v]])swap(u,v);
return dep[u]<dep[v]?u:v;
}
int kth(int u,int k){
while(k>=dfn[u]-dfn[top[u]]+1&&dfn[u]!=1)
k-=dfn[u]-dfn[top[u]]+1,u=fa[top[u]];
return que[dfn[u]-k];
}
int jump(int u,int v){
for(;top[u]!=top[v];u=fa[top[u]])
if(fa[top[u]]==v)return top[u];
return son[v];
}