样例过了全WA求助

B3609 [图论与代数结构 701] 强连通分量

lzg_070506 @ 2023-07-14 08:34:33

写法与常规Tarjan略有不同

#include<bits/stdc++.h>
using namespace std;
int n,m,ans;
int e[100010],ne[100010],h[10010],idx;
int dfn[10010],low[10010],ti;
int stk[10010],top;
bool st[10010];
struct SCC{//结构体方便排序
    int x,id;
    bool operator< (const SCC &ID)const{
        return id<ID.id;
    }
}I[10010];

void add(int a,int b){
    e[idx]=b;ne[idx]=h[a];h[a]=idx;idx++;
}

void tarjan(int u){
    ti++;
    dfn[u]=low[u]=ti;
    top++;
    stk[top]=u;
    st[u]=true;
    for(int i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(!dfn[j]){
            tarjan(j);
            low[u]=min(low[u],low[j]);
        }
        else if(st[j]) low[u]=min(low[u],dfn[j]);
    }
    if(dfn[u]==low[u]){
        int y=-1;
        ans++;
        int c=top,mi=u;
        while(y!=u){//寻找该连通分量中编号最小的点
            y=stk[c--];
            mi=min(mi,y);
        }
        y=-1;
        while(true){
            y=stk[top];top--;
            st[y]=false;
            I[y].id=mi;用分量内编号最小点编号标记
            if(y==u) break;
        }
    }
}

int main(){
    memset(h,-1,sizeof(h));
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        add(a,b);
    }
    for(int i=1;i<=n;i++){
        I[i].x=i;
        if(!dfn[i]){
            tarjan(i);
        }
    }
    sort(I+1,I+n+1);
    cout<<ans<<endl;
    int ii=I[1].id;
    for(int i=1;i<=n;i++){
        if(ii!=I[i].id){
            ii=I[i].id;
            cout<<endl;
        }
        cout<<I[i].x<<" ";
    }
    return 0;
}

|