黑科技——树剖两次dfs转一次dfs!
Posted dsjkafdsaf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了黑科技——树剖两次dfs转一次dfs!相关的知识,希望对你有一定的参考价值。
黑科技——树剖两次(dfs)转一次(dfs)!
重所周知,树链剖分通常是要(dfs?)两次的,就像这样:
int Fa[N],dep[N],Sz[N],son[N];
void dfs1(int x,int pre){
Fa[x]=pre,dep[x]=dep[pre]+1;
Sz[x]=1;
erep(i,G,x){
int y=G.to[i];
if(y==pre)continue;
dfs(y,x);
Sz[x]+=Sz[y];
(Sz[y]>Sz[son[x]])&&(son[x]=y);
}
}
int L[N],R[N],Id,top[N];
void dfs2(int x,int tp){
top[x]=tp;
if(son[x])dfs2(son[x],tp);
erep(i,G,x){
int y=G.to[i];
if(y==Fa[x]||y==son[x])continue;
dfs2(y,y);
}
}
但是在一些(n)比较大并且的卡常毒瘤题中,我们如果使用了两次(dfs)就有可能会出现(tle)的情况。
在这时,若我们无法优化本质算法的情况下我们需要卡常。
怎么卡呢?利用(dfs)序:
代码如下:
int Fa[N],dep[N],Sz[N],son[N],L[N],R[N],Id[N],cnt,top[N];
void dfs1(int x,int pre){
Fa[x]=pre,dep[x]=dep[pre]+1;
Sz[x]=1,L[x]=++cnt,Id[cnt]=x;
erep(i,G,x){
int y=G.to[i];
if(y==pre)continue;
dfs(y,x);
Sz[x]+=Sz[y];
(Sz[y]>Sz[son[x]])&&(son[x]=y);
}
R[x]=cnt;
}
rep(i,1,n)top[Id[i]]=Id[i]==son[Fa[Id[i]]]?top[Fa[Id[i]]]:Id[i];
就这样我们只用了一次(dfs)就完成了树剖的预处理操作。
别小看这一个递归,他在(n)较大的情况下,可以快大概(1)倍。
以上是关于黑科技——树剖两次dfs转一次dfs!的主要内容,如果未能解决你的问题,请参考以下文章