The two-Dfs method is just the DFS sweep again, and then the side reverse Dfs is swept over. A description of the challenge program.
Dual DFS code:
1#include <iostream>2#include <cstdio>3#include <cstring>4#include <vector>5 6 using namespacestd;7 Const intMAXN = 1e4 +5;8Vector <int> G[MAXN];//adjacency Table of graphs9Vector <int> RG[MAXN];//inverse adjacency Table of graphsTenVector <int> vs;//the vertex sequence table for post-order traversal One BOOLOK[MAXN];//access token A intNODE[MAXN];//number of strongly connected components - //First time Dfs - voidDfsintu) { theOk[u] =true; - for(inti =0; I < g[u].size (); i++) { - if(!Ok[g[u][i]]) - DFS (G[u][i]); + } - vs.push_back (u); + } A //Dfs for the second time at voidRdfsintU,intk) { -Node[u] =K; -Ok[u] =true; - for(inti =0; I < rg[u].size (); i++) { - if(!Ok[rg[u][i]]) - Rdfs (Rg[u][i], k); in } - } to + intMain () - { the intN, M, U, v; * while(~SCANF ("%d%d", &n, &m) && (n | |m)) { $ for(inti =1; I <= N; i++) {Panax Notoginseng g[i].clear (); - rg[i].clear (); theOk[i] =false; + vs.clear (); A } the for(inti =0; I < m; i++) { +scanf"%d%d", &u, &v); - G[u].push_back (v); $ rg[v].push_back (u); $ } - //The first time DFS selects any vertex as the starting point, the smaller the vertex order of the trailing traverse (leaf). - for(inti =1; I <= N; i++) { the if(!Ok[i]) - DFS (i);Wuyi } theMemset (OK,false,sizeof(OK)); - intK =0; Wu //the second time DFS traverses the edge backwards to mark the largest vertex as the starting point traversal so that the strongly connected components can be labeled - for(inti = vs.size ()-1; I >=0; i--) { About if(!Ok[vs[i]]) $Rdfs (Vs[i], + +k); - } - if(k >1) { -printf"no\n"); A } + Else { theprintf"yes\n"); - } $ } the}
Tarjan code, although more than a double Dfs, understanding is slightly more complex, but more useful, such as the evaluation of the LCA bridge, such as SCC problems.
Recommend a learning SCC blog, speak very well. https://www.byvoid.com/blog/tag/%E5%9C%96%E8%AB%96
The code is as follows:
1 //taking hdu1269 as an example2 //Strong connected component Tarjan algorithm3#include <iostream>4#include <cstdio>5#include <cstring>6#include <vector>7 using namespacestd;8 Const intMAXN = 1e4 +5;9Vector <int> G[MAXN];//Pro Connection TableTen BOOLINSTACK[MAXN];//I still in the stack One intSccnum, index;//number of connected components and time order A intTop, ST[MAXN];//storage i's simulation stack - intBLOCK[MAXN];//connected Components I belong to - intLOW[MAXN], DFN[MAXN];//I can get the first access to the point and timestamp the - voidTarjan (intu) { -St[++top] =u; -Instack[u] =true; +Low[u] = Dfn[u] = + +index; - for(inti =0; I < g[u].size (); i++) { + intv =G[u][i]; A if(!dfn[v]) {//V-Point has not been visited at Tarjan (v); - if(Low[v] < Low[u]) {//the time stamp (the root of the connected component) of the low[v] is represented by the U and V in a connected component . -Low[u] =Low[v]; - } - } - Else if(Instack[v]) {//v also shows in the stack that U and V are equivalent to one root of the connected component in a connected component (forming a loop) v inLow[u] =min (Low[u], dfn[v]); - } to } + intv; - if(Dfn[u] = = Low[u]) {//is the root of the connected component thesccnum++; * Do { $v = st[top--];Panax NotoginsengBLOCK[V] =Sccnum; -INSTACK[V] =false; the} while(V! = u);//all points of the connected component + } A } the + voidInitintN) { - for(inti =1; I <= N; i++) { $ g[i].clear (); $Instack[i] =false; -Dfn[i] =0; - } theSccnum = index = top =0; - }Wuyi the intMain () - { Wu intN, M, U, v; - while(~SCANF ("%d%d", &n, &m) && (n | |m)) { About init (n); $ for(inti =0; I < m; i++) { -scanf"%d%d", &u, &v); - G[u].push_back (v); - } A for(inti =1; I <= N; i++) { + if(!Dfn[i]) { the Tarjan (i); - } $ } the if(Sccnum >1) { thecout <<"no\n"; the } the Else { -cout <<"yes\n"; in } the } the}
Strongly connected components (Tarjan for strong connected components)