就我所知,有三种时间复杂度为O(n)的方法可以求强连通分量,分别是Kosaraju、Tarjan和Gabow。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
void dfs( int index) {
low[index] = dfn[index] = cnt++;
used[index] = 1;
del[index] = 0;
st[top++] = index;
for ( int i = last[index]; i!=-1; i = e[i].nxt)
if (!used[e[i].y]) {
dfs(e[i].y);
if (low[index]>low[e[i].y]) low[index] = low[e[i].y];
}
else if (!del[e[i].y]) if (low[index]>dfn[e[i].y])
low[index] = dfn[e[i].y];
if (low[index]==dfn[index]) {
do {
root[st[--top]] = index;
del[st[top]] = 1;
} while (st[top]!=index);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
const int MAXN = 1000;
struct node {
int tar;
node *nxt;
node( int _tar,node *_nxt)
: tar(_tar),nxt(_nxt) {}
};
node *g[MAXN];
int n,m,co,all,dfn[MAXN],id[MAXN];
stack< int > vec,path;
void dfs( int x) {
dfn[x] = co++;
vec.push(x);
path.push(x);
for (node *i = g[x]; i!=NULL; i = i->nxt)
if (dfn[i->tar]==-1) dfs(i->tar);
else if (id[i->tar]==-1)
while (dfn[path.top()]>dfn[i->tar]) path.pop();
if (path.top()==x) path.pop();
else return ;
for ( int i; ;) {
id[i = vec.top()] = all;
vec.pop();
if (i==x) break ;
}
all++;
}
int main() {
freopen ( "gabow.in" , "r" ,stdin);
freopen ( "gabow.out" , "w" ,stdout);
scanf ( "%d%d" ,&n,&m);
memset (g,0, sizeof (g));
for ( int i = 0,a,b; i<m; i++) {
scanf ( "%d%d" ,&a,&b); a--; b--;
g[a] = new node(b,g[a]);
}
co = all = 0;
memset (dfn,-1, sizeof (dfn));
memset (id,-1, sizeof (id));
for ( int i = 0; i<n; i++)
if (dfn[i]==-1) dfs(i);
for ( int i = 0; i<n; i++)
printf ( "%d\n" ,id[i]);
return 0;
}
|