¿Existe un algoritmo eficiente para enumerar todos los ciclos dentro del Componente fuertemente conectado de un gráfico dirigido?

DB Johnson, “Encontrando todos los circuitos elementales de un gráfico dirigido”, SIAM Journal of Computing , 4 (1), 1975 pp. 77–84.http: //dutta.csc.ncsu.edu/csc791….

Demostración de C ++

  / *
 [Formato de entrada SCC]
 los índices de vértice comienzan desde 0

 ---
 N = número de nodos en el SCC
 v1 OutDeg (v1) 
 v2 OutDeg (v2) 
 ...
 vN OutDeg (vN) 
 ----

 por ejemplo, para el gráfico dirigido completo de 3 vértices, la entrada es

 3
 0 2 1 2
 1 2 0 2
 2 2 0 1

 [Uso] ./a.out <input.txt
 * /

 #include 
 #include 
 #include 
 #include 

 usando el espacio de nombres estándar;

 typedef vector <list > AdjListT;
 AdjListT A, B;
 vector  node_stack;
 vector  bloqueado;
 tamaño_t s;

 anular UNBLOCK (size_t);
 bool CIRCUIT (size_t);
 OutputCycle vacío (vector  &);

 int main (nulo)
 {
     tamaño_t N, copia_de_N;
     cin >> N;
     copy_of_N = N;
     A.resize (N);
     bloqueado.resize (N);
     B.resize (N);

     mientras que (N--) {
         size_t u, v, out_degree;

         cin >> u >> out_degree;
         while (out_degree--) {
             cin >> v;
             A.at (u) .push_back (v);
         }
     }
     N = copia_de_N;
     para (size_t i = 0; i <N; ++ i)
         bloqueado [i] = falso;
     s = 0;
     mientras que (s <N) {
         CIRCUITO (s);

         A [s] .clear ();
         para (size_t i = 0; i <N; ++ i)
             A [i] .remove (s);
         para (size_t i = 0; i <N; ++ i) {
             bloqueado [i] = falso;
             B [i] .clear ();
         }

         ++ s;
     }
     devuelve 0;
 }

 bool CIRCUIT (size_t v)
 {
     bool f = falso;
     node_stack.push_back (v);
     bloqueado [v] = verdadero;
     for (list  :: iterator iw = A [v] .begin (); iw! = A [v] .end (); ++ iw) {
         size_t w = * iw;
         if (w == s) {
             OutputCycle (node_stack);
             f = verdadero;
         } más si (! bloqueado [w]) {
               si (CIRCUITO (w))
                   f = verdadero;
         }
     }
     si (f)
         DESBLOQUEO (v);
     más
        for (list  :: iterator iw = A [v] .begin (); iw! = A [v] .end (); ++ iw) {
            size_t w = * iw;
            if (find (B [w] .begin (), B [w] .end (), v) == B [w] .end ())
                B [w] .push_back (v);
         }

     node_stack.pop_back ();
     volver f;
 }

 ANULAR DESBLOQUEO (size_t u)
 {
     bloqueado [u] = falso;
     for (list  :: iterator iw = B [u] .begin (); iw! = B [u] .end ();) {
         size_t w = * iw;
         iw = B [u] .erase (iw);
         si (bloqueado [w])
             DESBLOQUEO (w);
     }
     regreso;
 }

 OutputCycle vacío (vector  & node_stack)
 {
     for (vector  :: iterator i = node_stack.begin (); i! = node_stack.end (); ++ i)
         cout << * i << "";
     cout << endl;
     regreso;
 }