In order to train small Greek sense of direction, Gardon built a large castle, inside the room there are N (N <= 10000) and M channels (M <= 100000), each channel is unidirectional, that if called a passage communicating the room a and room B, a room B can be reached only by the described rooms a through this channel, but does not indicate the room can reach a B room through it. Gardon need to ask you to write a program to confirm whether any two rooms are interconnected, namely: for any i and j, there is at least one path from room to room j i, j may also exist a path from room to the room i.
Input
The first line comprises a plurality of sets of input data, there are two input numbers: N and M, the next M lines each with two numbers, a and B, may represent a channel from A to B room room. File and end with two zeroes.
Output
For each set of input data, if any two rooms are connected with each other, and outputs "Yes", and otherwise outputs "No".
Sample Input
3 3 1 2 2 3 3 1 3 3 1 2 2 3 3 2 0 0
Sample Output
Yes No
Title effect: a directed graph, with n dots and m edges. FIG intensity is determined whether the entire communication, and if so, output Yes, otherwise, outputs No.
Topic Kosaraju algorithm and Tarjan algorithm can be used.
Comments from: "algorithm contest entry to advanced"
Kosaraju algorithm:
Kosaraju algorithm uses technology "anti map", based on the following two principles:
(1) a directed graph G, G to reverse all sides to build FIG anti rG, does not change the original anti-G rG FIG strong connectivity. That is, the number of G and SCC SCC same number of rG (Unicom intensity component).
(2) on the original image G and anti FIG rG each doing a DFS, may determine the number of SCC.
Code:
#pragma comment(linker, "/STACK:1024000000,1024000000") #pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<queue> #include<set> #include<cmath> #include<string> #include<map> #include<vector> #include<ctime> #include<stack> using namespace std; #define mm(a,b) memset(a,b,sizeof(a)) typedef long Long LL; const Long Long MOD = 1E9 + . 7 ; const int MAXN = 1E4 + 10 ; const int INF = 0x3f3f3f3f ; Vector < int > G [MAXN], of rG [MAXN]; Vector < int > S; // save the first DFS1 results: the marker sequence int VIS [MAXN], sccno [MAXN], CNT; // CNT is the number of connected components void DFS1 ( int U) { IF (VIS [U]) return ; VIS [U ] = 1 ; for ( int I = 0 ; I <G [U] .size (); I ++ ) DFS1 (G [U] [I]); S.push_back (U); // order of markers, marker large discharge in the back of S } void DFS2 ( int U) { IF (sccno [U]) return ; sccno [U] = CNT; for ( int I = 0 ; I <of rG [U] .size (); I ++ ) DFS2 ( of rG [U] [I]); } void Kosaraju ( int n-) { CNT = 0 ; S.clear (); mm (sccno, 0 ); mm (VIS,0); for(int i=1;i<=n;i++) dfs1(i); //点的编号:1~n递归所有点 for(int i=n-1;i>=0;i--) if(!sccno[S[i]]) { cnt++; dfs2(S[i]); } } int main() { int n,m,u,v; while(scanf("%d %d",&n,&m),n||m) { for(int i=0;i<n;i++) { G[i].clear(); rG[i].clear(); } for(int i=0;i<m;i++) { scanf("%d %d",&u,&v); G[u].push_back(v); rG[v].push_back(u); } Kosaraju(n); if(cnt==1) printf("Yes\n"); else printf("No\n"); } return 0; }
Tarjan algorithm
Above Kosaraju's algorithm, which is one approach to the SCC to "dig" out from FIG. Tarjan algorithm can put all the points are separated by SCC in DFS.
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #pragma GCC optimize(2) 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 #include<cstring> 7 #include<queue> 8 #include<set> 9 #include<cmath> 10 #include<string> 11 #include<map> 12 #include<vector> 13 #include<ctime> 14 #include<stack> 15 using namespace std; 16 #define mm (A, B) Memset (A, B, the sizeof (A)) . 17 typedef Long Long LL; 18 is const Long Long MOD = 1E9 + . 7 ; . 19 const int MAXN = 1E4 + 10 ; 20 is const int INF = 0x3f3f3f3f ; 21 is int CNT; // number of strongly connected components 22 is int Low [MAXN], NUM [MAXN], DFN; 23 is int sccno [MAXN]; 24 Stack < int > ST; 25 Vector < int >G [MAXN]; 26 is 27 void DFS ( int U) 28 { 29 st.push (U); 30 Low [U] NUM = [U] = ++ DFN; 31 is for ( int I = 0 ; I <G [ U] .size (); I ++ ) 32 { 33 is int V = G [U] [I]; 34 is IF (NUM [V])! // unvisited point, continuing the DFS 35 { 36 DFS (V); // bottom of DFS, the last the SCC 37 [ Low [U] = min (Low [V], Low [U]); 38 is } 39 the else IF (! Sccno [V]) // rolled back side 40 Low [U] = min (Low [U], NUM [V]); 41 is } 42 is IF (Low [U] == NUM [U] ) // point of the bottom of the stack is the ancestor of SCC, it NUM = Low 43 is { 44 is CNT ++ ; 45 the while ( . 1 ) 46 is { 47 int V = st.top (); // V pop the stack 48 st.pop () ; 49 sccno [V] = CNT; 50 IF (U == V) BREAK ; //Point stack bottom is SCC ancestor 51 is } 52 is } 53 is } 54 is 55 void Tarjan ( int n-) 56 is { 57 is CNT = DFN = 0 ; 58 mm (sccno, 0 ); 59 mm (NUM, 0 ); 60 mm ( Low, 0 ); 61 is for ( int I = . 1 ; I <= n-; I ++ ) 62 is IF (! NUM [I]) 63 is DFS (I); 64 } 65 66 int main() 67 { 68 int n,m,u,v; 69 while(scanf("%d %d",&n,&m),n||m) 70 { 71 for(int i=1;i<=n;i++) G[i].clear(); 72 for(int i=0;i<m;i++) 73 { 74 scanf("%d %d",&u,&v); 75 G[u].push_back(v); 76 } 77 Tarjan(n); 78 if(cnt==1) printf("Yes\n"); 79 else printf("No\n"); 80 } 81 return 0; 82 }