Skip to content

tarjan求点双连通分量 ​

  • 边双连通分量:极大的不含桥的连通块
  • 点双连通分量:极大的不含割点的连通块
  • 每个割点至少属于两个连通分量
  • 两个割点之间的边不一定是桥
cpp
int dfn[N],low[N],dcc_cnt,timestamp;
int h[N],e[M],ne[M],idx;
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
vector<int> dcc[N],st;
bool cut[N];
int root;
void tarjan(int u){
    dfn[u]=low[u]=++timestamp;
    st.push_back(u);
    if(u==root&&h[u]==-1){
        ++dcc_cnt;
        dcc[dcc_cnt].push_back(u);
        return;
    }
    int cnt=0;
    for(int i=h[u];~i;i=ne[i]){
        int v=e[i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
            if(dfn[u]<=low[v]){
                cnt++;
                if(u!=root||cnt>1)cut[u]=1;
                ++dcc_cnt;
                int y;
                do{
                    y=st.back();
                    st.pop_back();
                    dcc[dcc_cnt].push_back(y);
                }while(y!=v);
                dcc[dcc_cnt].push_back(u);   
            }
        }
        else low[u]=min(low[u],low[v]);
    }
}