点双连通分量模板

//Tarjan求割点
void tarjan(int now,int fa){
    int num=0;
    low[now]=dfn[now]=++dfnc;
    for(int i=head[now];i!=-1;i=b[i].next){
        int u=b[i].to;
        if(!dfn[u]){
            tarjan(u,now);
            low[now]=min(low[now],low[u]);
            if((fa==-1 && ++num>1) || (fa!=-1 && low[u]>=dfn[now])){  
                cut[now]=1;
            }
        }
        else if(u!=fa){
            low[now]=min(low[now],dfn[u]);
        }
    }
}
//Tarjan求点双
void tarjan(int now,int fa){
    low[now]=dfn[now]=++dfnc; 
    sta[++top]=now;
    for(int i=head[now];i!=-1;i=b[i].next){  
        int u=b[i].to;
        if(!dfn[u]){
            tarjan(u,now);
            low[now]=min(low[now],low[u]);
            if(dfn[now]<=low[u]){              
                ++num;
                while(sta[top+1]!=u){
			int w=sta[top--];
			dcc[num].push_back(w);
		}
                dcc[num].push_back(now);
            }
        }
        else if(u!=fa){
            low[now]=min(low[now],dfn[u]);
        }
    }
}
//Tarjan点双缩点(圆方树)
void tarjan(int xx,int fa){
    dfn[xx]=low[xx]=++dfc;
    sta[++top]=xx;
    num++;
    for(int i=head[xx];i!=-1;i=b[i].next){
        int u=b[i].to;
        if(!dfn[u]){
            tarjan(u,xx);
            low[xx]=min(low[xx],low[u]);
            if(low[u]>=dfn[xx]){
                n++;
                ad2(xx,n),ad2(n,xx);
                while(1){
                    int da=sta[top--];
                    ad2(da,n),ad2(n,da);
                    if(da==u) break;
                }
            }         
        } else if(u!=fa){
            low[xx]=min(low[xx],dfn[u]);
        }
    }
}
原文地址:https://www.cnblogs.com/liuchanglc/p/12812899.html