贴模板,备忘。
模板1:
1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string.h> 8 using namespace std; 9 struct node { 10 int v,next; 11 }edge[1001]; 12 int DFN[1001],LOW[1001]; 13 int stack[1001],heads[1001],visit[1001],cnt,tot,index; 14 void add(int x,int y) 15 { 16 edge[++cnt].next=heads[x]; 17 edge[cnt].v = y; 18 heads[x]=cnt; 19 return ; 20 } 21 void tarjan(int x)//代表第几个点在处理。递归的是点。 22 { 23 DFN[x]=LOW[x]=++tot;// 新进点的初始化。 24 stack[++index]=x;//进站 25 visit[x]=1;//表示在栈里 26 for(int i=heads[x];i!=-1;i=edge[i].next) 27 { 28 if(!DFN[edge[i].v]) {//如果没访问过 29 tarjan(edge[i].v);//往下进行延伸,开始递归 30 LOW[x]=min(LOW[x],LOW[edge[i].v]);//递归出来,比较谁是谁的儿子/父亲,就是树的对应关系,涉及到强连通分量子树最小根的事情。 31 } 32 else if(visit[edge[i].v ]){ //如果访问过,并且还在栈里。 33 LOW[x]=min(LOW[x],DFN[edge[i].v]);//比较谁是谁的儿子/父亲。就是链接对应关系 34 } 35 } 36 if(LOW[x]==DFN[x]) //发现是整个强连通分量子树里的最小根。 37 { 38 do{ 39 printf("%d ",stack[index]); 40 visit[stack[index]]=0; 41 index--; 42 }while(x!=stack[index+1]);//出栈,并且输出。 43 printf("\n"); 44 } 45 return ; 46 } 47 int main() 48 { 49 memset(heads,-1,sizeof(heads)); 50 int n,m; 51 scanf("%d%d",&n,&m); 52 int x,y; 53 for(int i=1;i<=m;i++) 54 { 55 scanf("%d%d",&x,&y); 56 add(x,y); 57 } 58 for(int i=1;i<=n;i++) 59 if(!DFN[i]) tarjan(i);//当这个点没有访问过,就从此点开始。防止图没走完 60 return 0; 61 }
模板2:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 #include<stack> 6 #define maxn 1005 7 using namespace std; 8 struct Edge 9 { 10 int next; 11 int to; 12 }edge[maxn]; 13 int head[maxn]; 14 int cnt; 15 int step; 16 int dfn[maxn];//表示深搜的步数; 17 int low[maxn];//表示能追溯到最早的栈中节点的次序; 18 int sccno[maxn];//缩点数组,表示每个点对应的缩点值; 19 int scc_cnt;//强连通分量的个数; 20 void init() 21 { 22 cnt=0; 23 step=0; 24 memset(head,-1,sizeof(head)); 25 } 26 void add(int u,int v) 27 { 28 edge[cnt].next=head[u]; 29 edge[cnt].to=v; 30 head[u]=cnt++; 31 } 32 vector<int>scc[maxn];//得出来的缩点,保存具体缩了那些点; 33 stack<int>s; 34 void dfs(int u) 35 { 36 dfn[u]=low[u]=++step; 37 s.push(u); 38 for(int i=head[u];i!=-1;i=edge[i].next) 39 { 40 int v=edge[i].to; 41 if(!dfn[v]) 42 { 43 dfs(v); 44 low[u]=min(low[u],low[v]); 45 } 46 else if(!sccno[v]) 47 { 48 low[u]=min(low[u],dfn[v]); 49 } 50 } 51 if(low[u]==dfn[u]) 52 { 53 scc_cnt++; 54 scc[scc_cnt].clear(); 55 while(1) 56 { 57 int x=s.top(); 58 s.pop(); 59 if(sccno[x]!=scc_cnt) 60 scc[scc_cnt].push_back(x); 61 sccno[x]=scc_cnt; 62 if(x==u) 63 break; 64 } 65 } 66 } 67 void tarjan(int n) 68 { 69 memset(sccno,0,sizeof(sccno)); 70 memset(dfn,0,sizeof(dfn)); 71 step=scc_cnt=0; 72 for(int i=1;i<=n;i++) 73 if(!dfn[i])dfs(i); 74 } 75 int main() 76 { 77 int n,m; 78 int x,y; 79 cin>>n>>m; 80 init(); 81 while(m--) 82 { 83 cin>>x>>y; 84 add(x,y); 85 } 86 tarjan(n); 87 cout<<scc_cnt<<endl; 88 return 0; 89 }
滚了。