tarjan-强连通分量
#include<iostream> #include<cstring> #include<vector> using namespace std; const int N=100010,M=1000010; int ver[M],Next[M],head[N],dfn[N],low[N]; int stack[N],ins[N],c[N]; vector<int> scc[N]; int n,m,tot,num,top,cnt; int hc[N],vc[N<<1],nc[N<<1],tc; void add(int x,int y){ ver[++tot]=y,Next[tot]=head[x],head[x]=tot; } void add_c(int x,int y){//缩点 vc[++tc]=y,nc[tc]=hc[x],hc[x]=tc; } void tarjan(int x){ dfn[x]=low[x]=++num; stack[++top]=x,ins[x]=1; for(int i=head[x];i;i=Next[i]) if(!dfn[ver[i]]){ tarjan(ver[i]); low[x]=min(low[x],low[ver[i]]); } else if(ins[ver[i]]) low[x]=min(low[x],dfn[ver[i]]); if(dfn[x]==low[x]){ cnt++; int y; do{ y=stack[top--],ins[y]=0; c[y]=cnt,scc[cnt].push_back(y); }while(x!=y); } } //c[x]表示x所在强连通分量的编号 //scc[i]记录了编号为i的强连通分量中的所有节点 //图***有cnt个强连通分量 int main(){ cin>>n>>m; for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int x=1;x<=n;x++)//缩点 for(int i=head[x];i;i=Next[i]){ int y=ver[i]; if(c[x]==c[y]) continue; add_c(c[x],c[y]); } return 0; }
9 13 1 2 1 5 1 6 2 3 3 4 4 5 5 2 6 8 6 7 7 4 8 7 8 9 9 6