結點第二次被訪問即為退出之時,那麼我們可以得到結點的退出順序: (2)倒轉每一條邊的方向,構造出一個反圖G’。然後按照退出順序的逆序對反圖進行第二次DFS遍歷。我們按1、4、2、3、5的逆序第二次DFS遍歷:
訪問過程如下: 每次遍歷得到的那些點即屬於同一個強連通分量。1、4屬於同一個強連通分量,2、3、5屬於另一個強連通分量。
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int map[101][101]; 6 int nmap[101][101]; 7 int pass[101]; 8 int vis[101]; 9 int now=1; 10 int n,m; 11 int num=0; 12 void dfs(int p) 13 { 14 vis[p]=1; 15 for(int i=1;i<=n;i++) 16 { 17 if(vis[i]==0&&map[p][i]==1) 18 { 19 dfs(i); 20 21 } 22 } 23 pass[now]=p; 24 now++; 25 } 26 void ndfs(int p) 27 { 28 vis[p]=0; 29 for(int i=1;i<=n;i++) 30 { 31 if(vis[i]==1&&nmap[p][i]==1) 32 ndfs(i); 33 } 34 } 35 int main() 36 { 37 38 scanf("%d%d",&n,&m); 39 for(int i=1;i<=m;i++) 40 { 41 int x,y; 42 scanf("%d%d",&x,&y); 43 map[x][y]=1; 44 nmap[y][x]=1; 45 } 46 for(int i=1;i<=n;i++) 47 { 48 if(vis[i]==0) 49 dfs(i); 50 } 51 pass[now]=1; 52 for(int i=n;i>=1;i--) 53 { 54 if(vis[pass[i]]==1) 55 { 56 ndfs(pass[i]); 57 num++; 58 } 59 } 60 cout<<num; 61 return 0; 62 }