*有向图强连通分量——Tarjan

来源:互联网 发布:xampp mysql mac设置 编辑:程序博客网 时间:2024/06/03 15:43
今天是2017/5/31,DCDCBigBig的第十四篇博文

Tarjan

#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<stack>using namespace std;struct edge{    int v,next;}a[100001];stack<int>s;int n,m,u,v,sum=0,tt=-1,ans=0,h[100001],anss[100001],num[100001],nums[100001],tot=0,tim=0,dfn[100001],low[100001],head[100001];bool used[100001],isin[100001];void tarjan(int u){    int v;    used[u]=isin[u]=true;    low[u]=dfn[u]=++tim;    s.push(u);    for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){        v=a[tmp].v;        if(!used[v]){            tarjan(v);            low[u]=min(low[u],low[v]);        }else{            if(isin[v])low[u]=min(low[u],dfn[v]);        }    }    if(low[u]==dfn[u]){        v=-1;        sum++;        while(v!=u){            v=s.top();            s.pop();            isin[v]=0;            num[v]=sum;            nums[sum]++;        }    }}void add(int u,int v){    a[++tot].v=v;    a[tot].next=head[u];    head[u]=tot;}int main(){    memset(used,0,sizeof(used));    memset(head,-1,sizeof(head));    memset(h,-1,sizeof(h));    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++){        scanf("%d%d",&u,&v);        add(u,v);    }    for(int i=1;i<=n;i++){        if(!used[i])tarjan(i);    }    tot=0;    for(int i=1;i<=n;i++){        for(int tmp=head[i];tmp!=-1;tmp=a[tmp].next){            if(num[i]!=num[a[tmp].v]){                h[num[i]]=++tot;            }        }    }    for(int i=1;i<=sum;i++){        if(nums[i]>1)ans++;    }    printf("%d\n",ans);    for(int i=1;i<=sum;i++){        if(h[i]==-1){             if(tt!=-1||nums[i]==1){                tt=-1;                break;             }else tt=i;        }    }    if(tt==-1)printf("-1");    else for(int i=1;i<=n;i++){        if(num[i]==tt)printf("%d ",i);    }    return 0;}/*6 71 22 33 24 24 55 66 4-------22 3*/

念完了。。。+1s