点双连通分量模板

//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(1){
					int w=sta[top--];
					dcc[num].push_back(w);
					if(w==u) break;
				}
				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]);
        }
    }
}
posted @ 2020-05-01 11:14  liuchanglc  阅读(234)  评论(0编辑  收藏  举报