模板强连通分量和tarjan算法
Posted Storm_Spirit
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板强连通分量和tarjan算法相关的知识,希望对你有一定的参考价值。
看了好久才终于明白了这个算法。。复杂度是O(n+m)。
我觉得这个算法不是很好理解,但是看懂了以后还是觉得听巧妙的。
下面给出模板代码和三组简单数据帮助理解。
代码如下:
1 #include <stdio.h> 2 #include <stack> 3 #include <algorithm> 4 #include <string.h> 5 #include <vector> 6 using namespace std; 7 8 const int N = 100+5; 9 10 stack<int> S; 11 int scc_cnt; //强连通分量的个数 12 int tot; //访问到该节点的时间戳 13 int belong[N]; //belong[i]表示i节点所属于第几个强连通分量 14 int dfn[N]; //表示第i个节点被访问的时间 15 int low[N]; //表示第i个节点的子节点所能访问到的最小的dfn值 16 vector<int> G[N]; 17 18 void dfs(int u) 19 { 20 dfn[u] = low[u] = ++tot; 21 S.push(u); 22 for(int i=0;i<G[u].size();i++) 23 { 24 int v = G[u][i]; 25 if(!dfn[v]) 26 { 27 dfs(v); 28 low[u] = min(low[u],low[v]); 29 } 30 else if(!belong[v]) //这句话等价于v在栈内 31 { 32 low[u] = min(low[u],low[v]); 33 //low[u] = min(low[u],dfn[v]); 34 //上面两种写法似乎都是没有问题的,但是如果仔细斟酌第三组数据和low的定义的话 35 //似乎是上面的写法更好,这里不敢确定,留个疑问。 36 } 37 } 38 if(low[u]==dfn[u]) 39 { 40 scc_cnt++; 41 for(;;) 42 { 43 //因为元素x只有在出栈了以后才被赋予归属,所以这就是上面等价的原因 44 int x = S.top();S.pop(); 45 belong[x] = scc_cnt; 46 if(x==u) break; 47 } 48 } 49 } 50 51 void scc(int n) 52 { 53 memset(dfn,0,sizeof(dfn)); 54 memset(belong,0,sizeof(belong)); 55 tot = scc_cnt = 0; 56 for(int i=0;i<n;i++) 57 { 58 if(!dfn[i]) dfs(i); 59 } 60 } 61 62 int main() 63 { 64 int n,m; 65 scanf("%d%d",&n,&m); 66 for(int i=0;i<m;i++) 67 { 68 int a,b; 69 scanf("%d%d",&a,&b); 70 G[a].push_back(b); 71 } 72 scc(n); 73 puts(""); 74 for(int i=0;i<n;i++) printf("%d %d %d %d\n",i,belong[i],dfn[i],low[i]); 75 printf("%d\n",scc_cnt); 76 return 0; 77 }
三组数据如下:
6 6 0 1 1 2 2 5 0 3 3 4 4 5 4 4 0 1 1 2 2 3 3 0 6 8 0 1 0 2 2 3 1 3 3 0 2 4 4 5 3 5
以上是关于模板强连通分量和tarjan算法的主要内容,如果未能解决你的问题,请参考以下文章