tarjan缩点

#include<bits/stdc++.h>
using namespace std;
const int N = 10005;
int n,m;
vector e (N,vector<int>());
vector ne (N,vector<int>());
vector<int>dfn(N) , low(N), stk(N),instk(N);
int tot,top,cnt;
vector<int>scc(N);
vector<int> w(N),nw(N),dp(N);
vector path(N,vector<int>());

void tarjan(int x){
    dfn[x]=low[x]=++tot;
    stk[++top]=x,instk[x]=1;
    for(int y : e[x]){
        if(!dfn[y]){
            tarjan(y);
            low[x] = min(low[x],low[y]);
        }
        else if(instk[y])
            low[x]=min(low[x],dfn[y]);
    }

    if(dfn[x]==low[x]){
        int y;++cnt;
        do{
            y=stk[top--];
            instk[y]=0;
            
            scc[y]=cnt;
            path[cnt].push_back(y);
        }while(y!=x);
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        e[u].push_back(v);
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i])tarjan(i);
    }
    //执行完之后有scc[i]=x(根据连通分量不同有不同的x);x取值1-cnt,cnt为总的连通分量个数
    cout<<cnt<<endl;
    vector<bool>vs(N,false);
    for(int i=1;i<=n;i++){
        int x = scc[i];
        auto v = path[x];
        if(vs[x]==false){
            sort(v.begin(),v.end());
            for(auto t : v){
                cout<<t<<" ";
            }
            cout<<endl;
        }
        vs[x]=true;
    }
}

posted @ 2025-08-10 09:02  majikko  阅读(23)  评论(0)    收藏  举报