无向图的点连通分量/割点

代码

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long LL;
const int N=10010;
int h[N],e[N],nex[N],idx,n,m,root;
int low[N],dfn[N],id[N],timestamp;
int sk[N],top;
bool cut[N];
int dcc_cnt;
vector<int> dcc[N]; //存储每个点连通分量内的点
void add(int x,int y){
    e[idx]=y;
    nex[idx]=h[x];
    h[x]=idx++;
}
void tarjan(int u){
    dfn[u]=low[u]=++timestamp;
    sk[top++]=u;
    if(u==root&&h[u]==-1){
        dcc_cnt++;
        dcc[dcc_cnt].push_back(u);
    }
    int cnt=0;
    for(int i=h[u];~i;i=nex[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]=true;
                ++dcc_cnt;
                int t;
                do{
                    t=sk[--top];
                    dcc[dcc_cnt].push_back(t);
                }while(v!=t);
                dcc[dcc_cnt].push_back(u);//割点属于多个点连通分量,割点的数量可以作为点连通分量的度
            }
        }
        else low[u]=min(low[u],dfn[v]);
    }
}
int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m;
    while(m--){
        int x,y;
        cin>>x>>y;
        add(x,y);
        add(y,x);
    }
    for(root=1;root<=n;++root){
        if(!dfn[root])
            tarjan(root);
    }
}
原文地址:https://www.cnblogs.com/jjl0229/p/12776076.html