tarjan算法
补一年前的坑。
有向图强连通分量
inline void tarjan(int x){
dfn[x]=low[x]=++dt,sta[++tp]=x,ins[x]=1;
forg(i,x)
if(!dfn[to[i]])tarjan(to[i]),low[x]=min(low[x],low[to[i]]);
else if(ins[to[i]])low[x]=min(low[x],dfn[to[i]]);
if(dfn[x]==low[x]){
++bn;int y;
do y=sta[tp--],ins[y]=0,bel[y]=bn;
while(x!=y);
}
}
low数组啥意思我也说不清,大概理解成一个辅助数组吧。。这个算法的妙处就在于,一个强联通分量的所有点,都会在标号最小的那个点那里被统计到。
无向图边双
inline void tarjan(int x,int e){
dfn[x]=low[x]=++dt;
forg(i,x)if(!dfn[to[i]]){
tarjan(to[i],i),low[x]=min(low[x],low[to[i]]);
if(low[to[i]]>dfn[x])br[i]=br[i^1]=1;
}else if(i!=(e^1))low[x]=min(low[x],low[to[i]]);
}
无向图点双
void tar(int x,int e){
dfn[x]=low[x]=++dn,tk[++tn]=x;
forg(i,x)if(i!=e){
int y=to[i];if(!dfn[y]){
tar(y,i^1),low[x]=min(low[x],low[y]);
if(low[y]==dfn[x]){
int z;do z=tk[tn--];while(z!=y);
}else if(low[y]>dfn[x])--tn;
}else low[x]=min(low[x],dfn[y]);
}
}
比有向图简单多了。