tpl_graph_utils.H

00001 
00002 /*
00003   This file is part of Aleph system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006
00006   UNIVERSITY LOS ANDES (ULA) Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA  
00007 
00008   - Center of Studies in Microelectronics & Distributed Systems (CEMISID) 
00009   - ULA Computer Science Department
00010   - FUNDACITE Mérida - Ministerio de Ciencia y Tecnología
00011 
00012   PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS
00013   DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT
00014   NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE
00015   SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS
00016   THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION.
00017 
00018   Aleph is distributed in the hope that it will be useful, but WITHOUT
00019   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020   or FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022   UNIVERSIDAD DE LOS ANDES requests users of this software to return to 
00023 
00024   Leandro Leon
00025   CEMISID 
00026   Ed La Hechicera 
00027   3er piso, ala sur
00028   Facultad de Ingenieria 
00029   Universidad de Los Andes 
00030   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00031 
00032   lrleon@ula.ve
00033 
00034   any improvements or extensions that they make and grant Universidad 
00035   de Los Andes (ULA) the rights to redistribute these changes. 
00036 
00037   Aleph is (or was) granted by: 
00038   - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA 
00039     (CDCHT)
00040   - Fundacite Mérida
00041 */
00042 
00043 
00044 # ifndef TPL_GRAPH_UTILS_H
00045 # define TPL_GRAPH_UTILS_H
00046 
00047 # include <ahPair.H>
00048 # include <tpl_graph.H> 
00049 # include <tpl_dynListQueue.H>
00050 
00051 using namespace Aleph;
00052 
00053 namespace Aleph {
00054 
00055       template <class GT> inline static bool 
00056   __depth_first_traversal(GT &                g, 
00057                           typename GT::Node * node,
00058                           typename GT::Arc *  arc,
00059                           bool                (*visit)(GT & g, 
00060                                                        typename GT::Node *, 
00061                                                        typename GT::Arc *),
00062                           size_t &            count);
00093       template <class GT> inline 
00094   size_t depth_first_traversal(GT &                g, 
00095                                typename GT::Node * start_node,
00096                                bool (*visit)(GT & g, typename GT::Node *, 
00097                                              typename GT::Arc *) )
00098   {
00099     g.reset_bit_nodes(Depth_First); // reiniciar bit Depth_First de los nodos
00100     g.reset_bit_arcs(Depth_First);  // reiniciar bit Depth_First de los arcos
00101 
00102     size_t counter = 0; // inicialmente no se ha visitado ningún nodo
00103 
00104         // iniciar la exploración recursiva
00105     __depth_first_traversal <GT> (g, start_node, NULL, visit, counter);
00106 
00107     return counter;
00108   }
00142       template <class GT> inline 
00143   size_t depth_first_traversal(GT & g, 
00144                                bool (*visit)(GT &, typename GT::Node *, 
00145                                              typename GT::Arc *) )
00146   {
00147     
00148     return depth_first_traversal <GT> (g, g.get_first_node(), visit);
00149   }
00150       template <class GT> inline static bool
00151   __depth_first_traversal(GT &                g, 
00152                           typename GT::Node * node, 
00153                           typename GT::Arc *  arc,
00154                           bool                (*visit)(GT & g, 
00155                                                        typename GT::Node *, 
00156                                                        typename GT::Arc *),
00157                           size_t &            count)
00158   {
00159     if (IS_NODE_VISITED(node, Depth_First)) // ¿Fue el nodo visitado?
00160       return false; // Sí ==> retorne y siga explorando
00161 
00162     NODE_BITS(node).set_bit(Depth_First, true); // marca nodo visitado
00163     count++;
00164 
00165         // Aquí se visita el nodo mediante la función de visita
00166 
00167     if (visit != NULL) // verifique si hay función de visita
00168       if ((*visit)(g, node, arc)) // sí, invóquela
00169         return true;
00170 
00171 
00172         // recorrer arcos de node y visitar recursivamente nodos conectados 
00173     for (typename GT::Node_Arc_Iterator it(node); it.has_current(); it.next())
00174       {
00175         typename GT::Arc * arc = it.get_current_arc();
00176 
00177         if (IS_ARC_VISITED(arc, Depth_First)) // ¿Ya se pasó por este arco?
00178           continue; // sí ==> ignórelo y vea el siguiente
00179 
00180         ARC_BITS(arc).set_bit(Depth_First, true); // marca arco actual visitado
00181 
00182         if (__depth_first_traversal(g, it.get_tgt_node(), arc, visit, count))
00183           return true; // ya se exploró cabalmente it.get_tgt_node()
00184       }
00185 
00186     return false; // retorne y siga explorando
00187   }
00220       template <class GT> inline size_t
00221   breadth_first_traversal(GT &                g, 
00222                           typename GT::Node * start,
00223                           bool (*visit)(GT &, typename GT::Node *, 
00224                                         typename GT::Arc *) )
00225   {
00226     g.reset_bit_nodes(Breadth_First); // reiniciar bit Breadth_First de nodos
00227     g.reset_bit_arcs(Breadth_First);  // reiniciar bit Breadth_First de arcos
00228 
00229     DynListQueue<typename GT::Arc*> q; // cola de arcos pendientes
00230 
00231         // ingresar a la cola los arcos de nodo start
00232     for (typename GT::Node_Arc_Iterator it(start); it.has_current(); it.next())
00233       q.put(it.get_current_arc());
00234 
00235     NODE_BITS(start).set_bit(Breadth_First, true); // marcar visitado start
00236 
00237     size_t node_counter = 0; // contador de nodos visitados
00238 
00239         // mientras queden arcos en la cola y no se hayan visitado todos
00240         // los nodos 
00241     while (not q.is_empty() and node_counter < g.get_num_nodes()) 
00242       {
00243         typename GT::Arc * arc = q.get(); // extraiga arco más cercano de la cola
00244 
00245         ARC_BITS(arc).set_bit(Breadth_First, true); // marcar arco
00246 
00247             // obtener nodos conectados al arco
00248         typename GT::Node * src = g.get_src_node(arc);
00249         typename GT::Node * tgt = g.get_tgt_node(arc);
00250 
00251         if (IS_NODE_VISITED(src, Breadth_First) and
00252             IS_NODE_VISITED(tgt, Breadth_First))
00253           continue; // si alguno de los nodos ha sido visitado entonces
00254                     // avanzamos al siguiente arco en la cola 
00255 
00256         typename GT::Node * visit_node = // seleccionar nodo a visitar
00257           IS_NODE_VISITED(src, Breadth_First) ? tgt : src;
00258 
00259              // Aquí se visita el nodo mediante la función de visita
00260 
00261         if (visit not_eq NULL)
00262           if ((*visit)(g, visit_node, arc))
00263             break;
00264 
00265 
00266         NODE_BITS(visit_node).set_bit(Breadth_First, true); 
00267         node_counter++;
00268 
00269             // insertar en cola arcos del nodo recién visitado
00270         for (typename GT::Node_Arc_Iterator it(visit_node); 
00271              it.has_current(); it.next())
00272           {
00273             typename GT::Arc * curr_arc = it.get_current_arc();
00274 
00275             if (IS_ARC_VISITED(curr_arc, Breadth_First))
00276               continue; // ya fue previamente introducido desde el otro nodo
00277 
00278                 // revise nodos del arcos para ver si han sido visitados
00279             if (IS_NODE_VISITED(g.get_src_node(curr_arc), Breadth_First) and 
00280                 IS_NODE_VISITED(g.get_tgt_node(curr_arc), Breadth_First))
00281               continue; // nodos ya visitados ==> no vale la pena meter el arco
00282 
00283             q.put(curr_arc);
00284           }
00285       }
00286 
00287     return node_counter;
00288   }
00324       template <class GT> inline size_t
00325   breadth_first_traversal(GT &                g, 
00326                           bool (*visit)(GT &, typename GT::Node *, 
00327                                         typename GT::Arc *)
00328                           )
00329   {
00330     return breadth_first_traversal(g, g.get_first_node(), visit);
00331   }
00332       template <class GT> inline static
00333   void __insert_in_queue(GT &                       g,
00334                          DynListQueue<Path<GT> *> & q,
00335                          typename GT::Node *        node,
00336                          typename GT::Arc *         arc,
00337                          Path<GT> *                 path_ptr = NULL)
00338   {
00339     auto_ptr<Path<GT> > path_auto;
00340 
00341     if (path_ptr == NULL)
00342       path_auto = // crear camino nuevo con origen en node
00343         auto_ptr<Path<GT> > ( new Path<GT> (g, node) );
00344     else
00345       path_auto = // crear copia de camino *path_ptr
00346         auto_ptr<Path<GT> > ( new Path<GT> (*path_ptr) );
00347     
00348     path_auto->append(arc); // añadir el nuevo arco
00349 
00350     q.put(path_auto.get()); // insertar el nuevo camino en cola
00351 
00352     path_auto.release();
00353   }
00376       template <class GT> inline 
00377   bool find_path_breadth_first(GT& g, 
00378                                typename GT::Node * start, 
00379                                typename GT::Node * end,
00380                                Path<GT> &          path)
00381   {
00382 
00383     if (not path.inside_graph(g))
00384       throw std::invalid_argument("Path does not belong to graph");
00385 
00386     path.clear_path(); // limpiamos cualquier cosa que esté en path
00387 
00388     g.reset_bit_nodes(Find_Path);
00389     g.reset_bit_arcs(Find_Path); 
00390 
00391     DynListQueue<Path<GT>*> q; // cola de caminos parciales
00392     Path<GT> * path_ptr = NULL; 
00393 
00394 
00395     try
00396       { 
00397 
00398             // insertar los caminos parciales con nodo inicio start 
00399         for (typename GT::Node_Arc_Iterator i(start); i.has_current(); i.next())
00400           __insert_in_queue<GT>(g, q, start, i.get_current_arc());
00401         
00402         NODE_BITS(start).set_bit(Find_Path, true); // márquelo visitado
00403 
00404         while (not q.is_empty()) // repetir mientras haya arcos sin visitar
00405           {
00406             path_ptr = q.get(); // extraiga camino actual
00407 
00408             typename GT::Arc * arc = path_ptr->get_last_arc(); 
00409 
00410             ARC_BITS(arc).set_bit(Find_Path, true); // marcar arco
00411 
00412             typename GT::Node * tgt = path_ptr->get_last_node();
00413             
00414             if (IS_NODE_VISITED(tgt, Find_Path)) // ¿visitó último nodo de camino?
00415               {     // sí ==> el camino no conduce al nodo end ==> borrar camino
00416                 delete path_ptr;
00417                 continue;
00418               }
00419 
00420             if (tgt == end) // ¿se encontró un camino?
00421               {     // sí ==> path_ptr contiene el camino buscado
00422                 path.swap(*path_ptr); // copiar resultado al parámetro path
00423 
00424                 while (not q.is_empty())
00425                   delete q.get();
00426 
00427                 delete path_ptr;
00428 
00429                 return true;
00430               }
00431 
00432             NODE_BITS(tgt).set_bit(Find_Path, true); // marcar último nodo camino
00433 
00434                 // insertar en cola arcos del nodo recién visitado
00435             for (typename GT::Node_Arc_Iterator i(tgt); i.has_current(); i.next())
00436               {
00437                 typename GT::Arc * curr_arc = i.get_current_arc();
00438 
00439                 if (IS_ARC_VISITED(curr_arc, Find_Path)) // ¿se visitó arco?
00440                   continue; // sí ==> avanzar al siguiente (ya fue visto)
00441 
00442                     // revise nodos del arco para ver si han sido visitados
00443                 if (IS_NODE_VISITED(g.get_src_node(curr_arc), Find_Path) and 
00444                     IS_NODE_VISITED(g.get_tgt_node(curr_arc), Find_Path))
00445                   continue; // nodos ya visitados ==> no vale la pena meter arco
00446 
00447                 __insert_in_queue<GT>(g, q, NULL, curr_arc, path_ptr);
00448               }
00449         
00450             delete path_ptr; // borrar camino extraído de la cola
00451           } // fin while (not q.is_empty())
00452 
00453       }
00454     catch (...) // hay excepción 
00455       { 
00456         while (not q.is_empty())
00457           delete q.get(); // antes de propagar excepción
00458 
00459         delete path_ptr;
00460 
00461         throw; // propagar la excepción
00462       }
00463 
00464 
00465     while (not q.is_empty())
00466       delete q.get();
00467 
00468     delete path_ptr;
00469 
00470     return false;
00471   }
00489       template <class GT> inline 
00490   bool test_connectivity(GT & g)
00491   {
00492         // un grafo con menos arcos que nodos no puede ser conexo
00493     if (not g.is_digraph() and g.get_num_arcs() < g.get_num_nodes() - 1)
00494       return false;
00495 
00496     return depth_first_traversal <GT> (g, NULL) == g.get_num_nodes();
00497   }
00519       template <class GT>
00520   bool is_reachable(GT & g, typename GT::Node * src, typename GT::Node * tgt)
00521   {
00522 
00523     if (not g.is_digraph())
00524       throw std::domain_error("g is not a digraph");
00525 
00526     return test_path(g, src, tgt);
00527   }
00528       template <class GT> inline static
00529   bool __test_cycle(GT &                g, 
00530                     typename GT::Node * src_node, 
00531                     typename GT::Node * curr_node);
00549       template <class GT> inline 
00550   bool test_cycle(GT & g, typename GT::Node * src_node)
00551   {
00552     g.reset_bit_nodes(Test_Cycle); // reiniciar bit Test_Cycle para los nodos
00553     g.reset_bit_arcs(Test_Cycle);  // reiniciar bit Test_Cycle para los arcos
00554 
00555         // explorar recursivamente a través de los arcos adyacentes a src_node
00556     for (typename GT::Node_Arc_Iterator it(src_node); it.has_current(); it.next())
00557       {
00558         typename GT::Arc * arc = it.get_current_arc();
00559 
00560         if (IS_ARC_VISITED(arc, Test_Cycle))
00561           continue;
00562 
00563         ARC_BITS(arc).set_bit(Test_Cycle, true); // pintar arco
00564         
00565             // ¿se encuentra un ciclo por el arco arc?
00566         if (__test_cycle <GT> (g, src_node, it.get_tgt_node()))
00567           return true; // sí ==> retornar true y detener la exploración
00568       }
00569         // En este punto se han explorado todos los caminos desde src_node
00570         // sin encontrar de nuevo a src_node ==> no existe ciclo 
00571     return false;
00572   }
00573       template <class GT> inline static
00574   bool __test_cycle(GT &                g, 
00575                     typename GT::Node * src_node, 
00576                     typename GT::Node * curr_node)
00577   {
00578     if (src_node == curr_node) // verificar si se alcanza nodo origen 
00579       return true; // ciclo detectado
00580 
00581     if (IS_NODE_VISITED(curr_node, Test_Cycle))
00582       return false; // ya se visitó este nodo 
00583 
00584     NODE_BITS(curr_node).set_bit(Test_Cycle, true); // marque nodo
00585 
00586         // busque los caminos desde current_node a ver si llega a src_node 
00587     for (typename GT::Node_Arc_Iterator it(curr_node); it.has_current(); 
00588          it.next())
00589       {
00590         typename GT::Arc * arc = it.get_current_arc();
00591 
00592         if (IS_ARC_VISITED(arc, Test_Cycle)) // se pasó por este arco?
00593           continue; // sí ==> ignorar y ver el próximo 
00594 
00595         ARC_BITS(arc).set_bit(Test_Cycle, true); // marque arco
00596             
00597         if (__test_cycle <GT> (g, src_node, it.get_tgt_node()))
00598           return true; // ciclo encontrado desde el arco actual 
00599       }
00600         // En este punto se han explorado todos los caminos desde curr_node
00601         // sin encontrar src_node ==> no existe ciclo que pase por curr_node  
00602     return false; 
00603   }  
00604       template <typename GT> inline static
00605   bool __is_acyclique(GT & g, typename GT::Node * curr_node)
00606   {
00607     if (IS_NODE_VISITED(curr_node, Is_Acyclique)) // ¿ha sido el nodo visitado?
00608       return false; // sí ==> se regresa desde arco no visitado ==> ciclo!
00609 
00610     NODE_BITS(curr_node).set_bit(Is_Acyclique, true); // marcar nodo
00611 
00612         // recorremos en profundidad curr_node 
00613     for (typename GT::Node_Arc_Iterator i(curr_node); i.has_current(); i.next())
00614       {
00615         typename GT::Arc * arc = i.get_current_arc();
00616 
00617         if (IS_ARC_VISITED(arc, Is_Acyclique)) 
00618           continue; // arco ya visitado, pase al siguiente
00619 
00620         ARC_BITS(arc).set_bit(Is_Acyclique, true); // pintar arco
00621 
00622             // ¿se detectó ciclo pasando por curr_node?
00623         if (not __is_acyclique(g, i.get_tgt_node()))
00624           return false; // sí ==> detenemos ejecución porque sabemos respuesta
00625       }
00626         // todos los arcos recorridos sin encontrar ciclo ==> el grafo es
00627         // acíclico pasando por curr_node
00628     return true; 
00629   }
00655       template <typename GT> inline 
00656   bool is_acyclique(GT & g, typename GT::Node * start_node)
00657   {
00658     if (not g.is_digraph() and g.get_num_arcs() >= g.get_num_nodes())
00659       return false; 
00660 
00661     g.reset_bit_arcs(Is_Acyclique);
00662     g.reset_bit_nodes(Is_Acyclique);
00663 
00664     return __is_acyclique(g, start_node);
00665   }    template <typename GT> inline 
00690   bool is_acyclique(GT & g)
00691   {
00692     if (not g.is_digraph() and g.get_num_arcs() >= g.get_num_nodes())
00693       return false; 
00694 
00695     g.reset_bit_arcs(Is_Acyclique);
00696     g.reset_bit_nodes(Is_Acyclique);
00697 
00698         // recorrer todos los nodos
00699     for (typename GT::Node_Iterator it(g); it.has_current(); it.next())
00700       {
00701         typename GT::Node * current_node = it.get_current_node();
00702 
00703         if (IS_NODE_VISITED(current_node, Is_Acyclique)) 
00704           continue; // nodo ya probado, avance al siguiente
00705         
00706             // ¿es acíclico desde current_node?
00707         if (not __is_acyclique(g, current_node)) 
00708           return false; // sí ==>
00709       }
00710     return true;
00711   }
00735   template <typename GT> inline bool has_cycle(GT & g)
00736   {
00737     return not is_acyclique(g);
00738   }
00739       template <class GT> inline static
00740   bool __test_path(GT&                 g, 
00741                    typename GT::Node * curr_node,  // nodo procedencia
00742                    typename GT::Node * end_node);  // arco destino
00762       template <class GT> inline 
00763   bool test_path(GT&                 g, 
00764                  typename GT::Node * start_node, 
00765                  typename GT::Node * end_node)
00766   {
00767         // si el grafo es conexo ==> existe camino
00768     if (not g.is_digraph() and g.get_num_arcs() >= g.get_num_nodes())
00769       return true;
00770 
00771     g.reset_bit_nodes(Test_Path);  // reiniciar bit Test_Path para nodos y arcos
00772     g.reset_bit_arcs(Test_Path);
00773 
00774         // buscar recursivamente caminos por arcos adyacentes a start_node
00775     for (typename GT::Node_Arc_Iterator i(start_node); i.has_current(); i.next())
00776       {
00777         typename GT::Arc * arc = i.get_current_arc();
00778 
00779         ARC_BITS(arc).set_bit(Test_Path, true); // marcar arco
00780 
00781             // ¿existe camino hasta end_node pasando por arc?
00782         if (__test_path(g, i.get_tgt_node(), end_node))
00783           return true; // sí, retornar 
00784       }
00785         // todos los arcos de start_node han sido explorados sin encontrar un
00786         // camino hasta end_node ==> no existe camino
00787     return false;
00788   }
00789       template <class GT> inline static
00790   bool __test_path(GT &                g, 
00791                    typename GT::Node * curr_node, // nodo procedencia
00792                    typename GT::Node * end_node)  // arco destino
00793   {
00794     if (curr_node == end_node) // ¿se encontró end_node?
00795       return true; // sí ==> existe camino; retornar true
00796 
00797     if (IS_NODE_VISITED(curr_node, Test_Path)) // ¿Ya se visitó curr_node?
00798       return false; // sí, no explore
00799 
00800     NODE_BITS(curr_node).set_bit(Test_Path, true); // pintar curr_node
00801 
00802         // buscar recursivamente a través de arcos de curr_node 
00803     for (typename GT::Node_Arc_Iterator i(curr_node); i.has_current(); i.next())
00804       {
00805         typename GT::Arc * arc = i.get_current_arc();
00806         
00807         if (IS_ARC_VISITED(arc, Test_Path)) // ¿Ya se vio este arco?
00808           continue; // sí, ignórelo y siga al siguiente 
00809 
00810         ARC_BITS(arc).set_bit(Test_Path, true); // pintar arco
00811         
00812             // buscar camino por el arco actual arc 
00813         if (__test_path <GT> (g, i.get_tgt_node(), end_node))
00814           return true;
00815       }
00816         // todos los arcos adyacente de curr_node fueron explorados sin
00817         // encontrar a end_node ==> no existe camino pasando por curr_node
00818     return false;
00819   }
00820       template <class GT> inline 
00821   void inconnected_components(GT & g, DynDlist<GT> & list);
00822       template <class GT> inline 
00823   void build_subgraph(GT &                g,           // grafo original
00824                       GT &                sg,          // componente inconexo
00825                       typename GT::Node * g_src,       // nodo actual en g
00826                       size_t &            node_count); // contador de nodos
00853       template <class GT> inline 
00854   void inconnected_components(GT & g, DynDlist <GT> & list)
00855   {
00856     g.reset_nodes(); 
00857     g.reset_arcs();  
00858 
00859     size_t count = 0; // contador de nodos visitados
00860 
00861         // Recorrer todos los nodos de g
00862     for (typename GT::Node_Iterator i(g);
00863          count < g.get_num_nodes() and i.has_current(); i.next())
00864       {
00865         typename GT::Node * curr_node = i.get_current_node();
00866 
00867         if (IS_NODE_VISITED(curr_node, Build_Subtree))
00868           continue;; // nodo ya fue visitado en otro recorrido, avance al próximo
00869 
00870             // crear subgrafo donde se colocará el componente inconexo que se
00871             // descubrirá a partir de curr_node 
00872         list.append(GT()); // crea subgrafo y lo inserta en lista
00873 
00874         GT & subgraph = list.get_last(); // obtiene una referencia al grafo
00875                                          // recién creado e insertado en list
00876 
00877             // construir subgrafo conexo a partir de curr_node
00878         build_subgraph(g, subgraph, curr_node, count); 
00879       }
00880   }
00911       template <class GT> inline 
00912   void build_subgraph(GT &                g,      // grafo original
00913                       GT &                sg,     // subgrafo componente inconexo
00914                       typename GT::Node * g_src,  // nodo actual en g
00915                       size_t &            node_count)
00916   {
00917 
00918     if (sg.get_num_nodes() != 0)
00919       throw std::domain_error("sg is not empty");
00920 
00921     if (IS_NODE_VISITED(g_src, Build_Subtree))
00922       return;
00923 
00924     NODE_BITS(g_src).set_bit(Build_Subtree, true); // marcar g_src visitado
00925     ++node_count; 
00926 
00927     typename GT::Node * sg_src =  // obtener imagen de g_src en sg
00928       static_cast<typename GT::Node *>(NODE_COOKIE(g_src));
00929 
00930     if (sg_src == NULL) // ¿está mapeado g_src?
00931       {     // No, cree imagen de g_src en el subgrafo sg y mapee
00932         sg_src = sg.insert_node(g_src->get_info());
00933         GT::map_nodes(g_src, sg_src);
00934       }
00935 
00936         // explore en profundidad a partir de g_src 
00937     for (typename GT::Node_Arc_Iterator i(g_src); 
00938          node_count < g.get_num_nodes() and i.has_current(); i.next())
00939       {
00940         typename GT::Arc * arc = i.get_current_arc();
00941 
00942         if (IS_ARC_VISITED(arc, Build_Subtree))
00943           continue; // avance a próximo arco
00944 
00945         ARC_BITS(arc).set_bit(Build_Subtree, true); // marque arc visitado
00946 
00947             // ahora observe el nodo destino del arco
00948         typename GT::Node * g_tgt  = i.get_tgt_node();  
00949         typename GT::Node * sg_tgt = 
00950           static_cast<typename GT::Node *>(NODE_COOKIE(g_tgt));
00951 
00952         if (sg_tgt == NULL) // ¿está mapeado en sg?
00953           {    // no, hay que mapearlo e insertarlo en el subgrafo sg
00954             sg_tgt = sg.insert_node(g_tgt->get_info()); 
00955             GT::map_nodes(g_tgt, sg_tgt); 
00956           }
00957 
00958             // tenemos los nodos en el subgrafo, insertamos el arco
00959         typename GT::Arc * sg_arc = 
00960           sg.insert_arc(sg_src, sg_tgt, arc->get_info());
00961 
00962         GT::map_arcs(arc, sg_arc); 
00963         
00964             // continue recorriendo en profundidad y construyendo el subgrafo
00965         build_subgraph(g, sg, g_tgt, node_count);
00966       }
00967   }
00995       template <class GT> inline 
00996   void strongly_connected_components(GT & g, DynDlist <GT> & list)
00997   {
00998 
00999     if (not g.is_digraph())
01000       throw std::domain_error("g is not a digraph");
01001 
01002     inconnected_components(g, list);
01003   }
01032       template <class GT> inline
01033   bool find_depth_first_spanning_tree(GT &                g, 
01034                                       typename GT::Node * gnode, 
01035                                       GT &                tree)
01036   {
01037     g.reset_nodes();
01038     g.reset_arcs(); 
01039 
01040     tree.clear_graph(); // asegurar que árbol destino esté vacío
01041 
01042     NODE_BITS(gnode).set_bit(Spanning_Tree, true); // marcar gnode
01043 
01044         // crear imagen de start_node en árbol abarcador y mapearla
01045     typename GT::Node * tnode = tree.insert_node(gnode->get_info());
01046     GT::map_nodes(gnode, tnode);
01047     for (typename GT::Node_Arc_Iterator i(gnode); i.has_current(); i.next())
01048       {
01049         typename GT::Arc * arc = i.get_current_arc();
01050 
01051         if (IS_ARC_VISITED(arc, Spanning_Tree))
01052           continue;
01053 
01054         typename GT::Node * arc_tgt_node = i.get_tgt_node();
01055 
01056         if (IS_NODE_VISITED(arc_tgt_node, Spanning_Tree))
01057           continue; // nodo destino también ya ha sido visitado desde otro arco
01058 
01059         if (__find_depth_first_spanning_tree(g, arc_tgt_node, arc, tree, tnode))
01060           return false; // ya el árbol está calculado 
01061       }
01062 
01063     return true;
01064   }
01091       template <class GT> inline
01092   typename GT::Node * find_depth_first_spanning_tree(GT & g, GT & tree)
01093   {
01094     typename GT::Node * start_node = g.get_first_node();
01095 
01096     if (not find_depth_first_spanning_tree(g, start_node, tree))
01097       return NULL;
01098 
01099     return start_node;
01100   }
01101       template <class GT> inline static
01102   bool __find_depth_first_spanning_tree(GT &                g, 
01103                                         typename GT::Node * gnode, 
01104                                         typename GT::Arc *  garc, 
01105                                         GT &                tree,
01106                                         typename GT::Node * tnode)
01107   {
01108     NODE_BITS(gnode).set_bit(Spanning_Tree, true); // marcar nodo 
01109     ARC_BITS(garc).set_bit(Spanning_Tree, true);   // marcar arco
01110 
01111         // insertar tgt_node en árbol y mapearlo
01112     typename GT::Node * tree_tgt_node = tree.insert_node(gnode->get_info());
01113     GT::map_nodes(gnode, tree_tgt_node);
01114 
01115         // insertar arc en árbol y mapearlo
01116     typename GT::Arc * tarc = 
01117       tree.insert_arc(tnode, tree_tgt_node, garc->get_info()); 
01118     GT::map_arcs(garc, tarc);
01119 
01120     tnode = tree_tgt_node; // esto hace que el bloque de recorrido sea el mismo
01121     
01122     if (tree.get_num_nodes() == g.get_num_nodes()) // ¿se ha abarcado el grafo?
01123       return true; // tree ya contiene el árbol abarcador
01124 
01125 
01126     I(tree.get_num_nodes() > tree.get_num_arcs()); // debe ser acíclico
01127 
01128     for (typename GT::Node_Arc_Iterator i(gnode); i.has_current(); i.next())
01129       {
01130         typename GT::Arc * arc = i.get_current_arc();
01131 
01132         if (IS_ARC_VISITED(arc, Spanning_Tree))
01133           continue;
01134 
01135         typename GT::Node * arc_tgt_node = i.get_tgt_node();
01136 
01137         if (IS_NODE_VISITED(arc_tgt_node, Spanning_Tree))
01138           continue; // nodo destino también ya ha sido visitado desde otro arco
01139 
01140         if (__find_depth_first_spanning_tree(g, arc_tgt_node, arc, tree, tnode))
01141           return false; // ya el árbol está calculado 
01142       }
01143 
01144     return false;
01145   }
01175       template <class GT> inline
01176   void find_breadth_first_spanning_tree(GT &                g, 
01177                                         typename GT::Node * gnode, 
01178                                         GT &                tree)
01179   {
01180     g.reset_bit_nodes(Spanning_Tree);
01181     g.reset_bit_arcs(Spanning_Tree);
01182 
01183         // inicialice árbol e inserte copia mapeada de gnode
01184     tree.clear_graph();
01185     auto_ptr<typename GT::Node> tnode_auto (new typename GT::Node(gnode));
01186     tree.insert_node(tnode_auto.get());
01187     GT::map_nodes(gnode, tnode_auto.release());
01188 
01189         // recorra arcos de gnode e insértelos en cola
01190     DynListQueue<typename GT::Arc*> q;
01191     for (typename GT::Node_Arc_Iterator i(gnode); i.has_current(); i.next())
01192       q.put(i.get_current_arc());
01193 
01194     NODE_BITS(gnode).set_bit(Spanning_Tree, true); // marque visitado gnode
01195 
01196     while (not q.is_empty()) // repita mientras queden arcos en la cola
01197       {
01198         typename GT::Arc * garc = q.get();
01199 
01200         ARC_BITS(garc).set_bit(Spanning_Tree, true); // marque visitado garc
01201 
01202             // obtenga nodos del arco en g garc
01203         typename GT::Node * gsrc = g.get_src_node(garc); 
01204         typename GT::Node * gtgt = g.get_tgt_node(garc);
01205 
01206         if (IS_NODE_VISITED(gsrc, Spanning_Tree) and
01207             IS_NODE_VISITED(gtgt, Spanning_Tree))
01208           continue; // los dos nodos del arco ya fueron visitados
01209 
01210             // decidir cual es el nodo ya marcado y mapeado
01211         if (IS_NODE_VISITED(gtgt, Spanning_Tree)) // ¿es gtgt?
01212           Aleph::swap(gsrc, gtgt); // sí, intercámbielo con gsrc
01213           
01214         typename GT::Node * tsrc = // obtener imagen de gsrc en tree
01215           static_cast<typename GT::Node*>(NODE_COOKIE(gsrc));
01216 
01217         NODE_BITS(gtgt).set_bit(Spanning_Tree, true); // marque gtgt visitado
01218 
01219             // crear copia de gtgt, insertarlo en tree y mapearlo
01220         auto_ptr<typename GT::Node> ttgt_auto (new typename GT::Node(gtgt));
01221         tree.insert_node(ttgt_auto.get());
01222         typename GT::Node * ttgt = ttgt_auto.release();
01223         GT::map_nodes(gtgt, ttgt);
01224 
01225             // insertar nuevo arco en tree y mapearlo
01226         typename GT::Arc * tarc = tree.insert_arc(tsrc, ttgt, garc->get_info());
01227         GT::map_arcs(garc, tarc);
01228 
01229         if (tree.get_num_nodes() == g.get_num_nodes()) // ¿tree abarca a g?
01230           break; // sí, terminar
01231 
01232             // insertar en cola arcos de gtgt
01233         for (typename GT::Node_Arc_Iterator i(gtgt); i.has_current(); i.next())
01234           {
01235             typename GT::Arc * current_arc = i.get_current_arc();
01236 
01237             if (IS_ARC_VISITED(current_arc, Spanning_Tree))
01238               continue; // ya fue previamente introducido desde el otro nodo
01239 
01240                 // revise nodos de arcos para ver si han sido visitados
01241             if (IS_NODE_VISITED(g.get_src_node(current_arc), Spanning_Tree) and 
01242                 IS_NODE_VISITED(g.get_tgt_node(current_arc), Spanning_Tree))
01243               continue; // nodos ya visitados ==> no vale la pena meter el arco
01244 
01245             q.put(current_arc);
01246           }
01247       }
01248   }
01249   template <class GT> inline static long & df(typename GT::Node * p)
01250 
01251   {
01252     return NODE_COUNTER(p);
01253   }
01254 
01255   template <class GT> inline static long & low(typename GT::Node * p)
01256 
01257   {
01258     return reinterpret_cast<long&>(NODE_COOKIE(p));
01259   }
01260 
01261       template <typename GT>
01262   struct Init_Low
01263   {
01264     void operator () (GT & g, typename GT::Node * node)
01265     {
01266       g.reset_counter(node); // inicializa df
01267       low <GT> (node) = -1;  // inicializa low
01268     }
01269   };
01270 
01271       template <typename GT> inline static
01272   void __compute_cut_nodes(GT &                            g, 
01273                            DynDlist<typename GT::Node *> & list, 
01274                            typename GT::Node *             p,
01275                            typename GT::Arc *              a,
01276                            long &                          curr_df);
01277 
01311       template <typename GT>
01312   void compute_cut_nodes(GT &                            g, 
01313                          typename GT::Node *             start,
01314                          DynDlist<typename GT::Node *> & list)
01315   {
01316     g.template operate_on_nodes <Init_Low <GT> > ();
01317     g.reset_arcs();
01318 
01319     long current_df = 0; // contador global de visitas 
01320 
01321     NODE_BITS(start).set_bit(Depth_First, true); // pintar visitado start
01322     df <GT> (start) = current_df++;
01323       
01324     int call_counter = 0; // contador de llamadas recursivas
01325         // Recorra los arcos de start mientras g no haya sido abarcado
01326     for (typename GT::Node_Arc_Iterator i(start); 
01327          i.has_current() and current_df < g.get_num_nodes(); 
01328          i.next())
01329     {
01330       typename GT::Node * tgt = i.get_tgt_node();
01331 
01332       if (IS_NODE_VISITED(tgt, Depth_First))
01333         continue; 
01334 
01335       typename GT::Arc * arc = i.get_current_arc();
01336         
01337       if (IS_ARC_VISITED(arc, Depth_First))
01338         continue;
01339 
01340       ARC_BITS(arc).set_bit(Depth_First, true);
01341 
01342       __compute_cut_nodes(g, list, tgt, arc, current_df); 
01343       ++call_counter;
01344     }  
01345     if (call_counter > 1) // ¿es la raíz un punto de articulación?
01346     {
01347       NODE_BITS(start).set_bit(Cut, true);
01348       list.append(start);
01349     }
01350   }
01351 
01352       template <typename GT> inline static
01353   void __compute_cut_nodes(GT &                            g, 
01354                            DynDlist<typename GT::Node *> & list, 
01355                            typename GT::Node *             p,
01356                            typename GT::Arc  *             a,
01357                            long &                          curr_df)
01358                    
01359   {
01360     NODE_BITS(p).set_bit(Depth_First, true); // pinte p como visitado
01361     low <GT> (p) = df <GT> (p) = curr_df++; // asígnele df
01362 
01363         // Recorrer recursivamente arcos de p mientras g no haya sido abarcado
01364     bool p_is_cut_node = false;
01365     for (typename GT::Node_Arc_Iterator i(p); i.has_current(); i.next())
01366       {
01367         typename GT::Arc * arc = i.get_current_arc();
01368    
01369         if (arc == a) // ¿es el arco del padre? 
01370           continue; // sí ==> avance al siguiente arco
01371 
01372         typename GT::Node * tgt = i.get_tgt_node(); // nodo destino de arc
01373         
01374         if (IS_NODE_VISITED(tgt, Depth_First)) 
01375           { 
01376             if (not IS_ARC_VISITED(arc, Depth_First)) // ¿es arco no-abarcador? 
01377               if (df <GT> (tgt) < low <GT> (p)) // sí, verificar valor de low
01378                 low <GT> (p) = df <GT> (tgt); // actualizar low(p)
01379 
01380             continue;
01381           }
01382 
01383         if (IS_ARC_VISITED(arc, Depth_First)) // ¿arco ya visitado?
01384           continue; // sí ==> avance al siguiente
01385 
01386         ARC_BITS(arc).set_bit(Depth_First, true); // marque arco
01387 
01388         __compute_cut_nodes(g, list, tgt, arc, curr_df);
01389 
01390         if (low <GT> (tgt) < low <GT> (p)) // verificar hijo de p - low(tgt) 
01391           low <GT> (p) = low <GT> (tgt); // actualizar low(p)
01392 
01393             // detección de nodo de corte
01394         if (low <GT> (tgt) >= df <GT> (p) and df <GT> (tgt) != 0)
01395           p_is_cut_node = true;
01396       }
01397         // p fue explorado recursivamente
01398     if (p_is_cut_node)
01399       {
01400         NODE_BITS(p).set_bit(Cut, true);
01401         list.append(p);
01402       }
01403   }
01444       template <typename GT>
01445   void compute_cut_nodes(GT &                            g, 
01446                          DynDlist<typename GT::Node *> & list)
01447   {
01448     compute_cut_nodes(g, g.get_first_node(), list);
01449   }
01450   const long Cross_Arc = -1;
01451       template <typename GT> inline static 
01452   bool is_a_cross_arc(typename GT::Arc * a)
01453   {
01454     return ARC_COUNTER(a) == Cross_Arc;
01455   }
01456      template <typename GT> inline static 
01457   bool is_a_cut_node(typename GT::Node * p)
01458   {
01459     return NODE_BITS(p).get_bit(Cut);
01460   }
01461 
01462       template <typename GT> inline static 
01463   bool is_an_cut_arc(typename GT::Arc * a)
01464   {
01465     return ARC_BITS(a).get_bit(Cut);
01466   }
01467       template <typename GT> inline static 
01468   bool is_node_painted(typename GT::Node * p)
01469   {
01470     return NODE_COUNTER(p) > 0;
01471   }
01472 
01473       template <typename GT> inline static 
01474   bool is_arc_painted(typename GT::Arc * arc)
01475   {
01476     return ARC_COUNTER(arc) > 0;
01477   }
01478 
01479       template <typename GT> inline static 
01480   void paint_node(typename GT::Node * p, const long & color)
01481   {
01482     NODE_COUNTER(p) = color;
01483   }
01484 
01485       template <typename GT> inline static 
01486   void paint_arc(typename GT::Arc * a, const long & color)
01487   {
01488     ARC_COUNTER(a) = color;
01489   }
01490 
01491       template <typename GT> inline static 
01492   const long & get_color(typename GT::Node * p)
01493   {
01494     return NODE_COUNTER(p);
01495   }
01496 
01497       template <typename GT> inline static 
01498   const long & get_color(typename GT::Arc * a)
01499   {
01500     return ARC_COUNTER(a);
01501   }
01502       template <typename GT> inline static
01503   void __paint_subgraph(typename GT::Node * p, // Nodo actual
01504                         typename GT::Arc *  a, // Arco que conduce a p
01505                         const long &        current_color)
01506   {
01507     if (is_a_cut_node  <GT>  (p)) // ¿es un nodo de corte?
01508       return; // Sí, ignórelo
01509    
01510     paint_arc <GT> (a, current_color); 
01511 
01512     if (is_node_painted <GT> (p)) // ¿ya está el nodo pintado?
01513       return; // Sí, ignórelo
01514 
01515     paint_node <GT> (p, current_color);
01516 
01517         // recorrer y pintar recursivamente el bloque a través de arcos de p
01518     for (typename GT::Node_Arc_Iterator it(p); it.has_current(); it.next())
01519       {
01520         typename GT::Arc * arc = it.get_current_arc();
01521 
01522         if (is_arc_painted <GT> (arc)) 
01523           continue;
01524 
01525         __paint_subgraph <GT> (it.get_tgt_node(), arc, current_color);
01526       }
01527   }
01528       template <typename GT> inline static
01529   void __paint_subgraph(typename GT::Node * p, // Nodo de inicio
01530                         const long &        current_color)
01531   {
01532 
01533     I(not is_a_cut_node <GT> (p) and not is_node_painted <GT> (p));
01534 
01535     paint_node <GT> (p, current_color);
01536 
01537     for (typename GT::Node_Arc_Iterator it(p); it.has_current(); it.next())
01538       {
01539         typename GT::Arc * arc = it.get_current_arc();
01540 
01541         if (is_arc_painted <GT> (arc)) 
01542           continue;
01543 
01544             // recorrer y pintar recursivamente el bloque a través de arcos de p
01545         __paint_subgraph <GT> (it.get_tgt_node(), arc, current_color);
01546       }
01547   }
01548       template <typename GT> inline static
01549   void __paint_from_cut_node(typename GT::Node *           p, // un nodo de corte
01550                              long &                        current_color)
01551   {
01552 
01553     I(is_a_cut_node <GT> (p));
01554 
01555         // pintar recursivamente con distintos colores los bloques conectados a p
01556     for (typename GT::Node_Arc_Iterator it(p); it.has_current(); it.next())
01557       {
01558         typename GT::Arc * arc = it.get_current_arc();
01559 
01560 
01561         I(not is_arc_painted <GT> (arc));
01562 
01563         typename GT::Node * tgt_node = it.get_tgt_node();
01564 
01565         if (is_a_cut_node <GT> (tgt_node)) // ¿ es un arco de corte?
01566           {
01567             ARC_BITS(arc).set_bit(Cut, true); // marque arco como de corte
01568             continue; // avance a próximo arco
01569           }
01570         else 
01571           {
01572             paint_arc <GT> (arc, Cross_Arc); // marque arco como de cruce
01573 
01574             if (is_node_painted <GT> (tgt_node)) // ¿pintado el nodo destino?
01575               continue; // sí, avanzar entonces al próximo arco
01576           }
01577 
01578             // pintar recursivamente con current_color el nodo conectado a arc
01579             // (que no es ni de corte ni de cruce) 
01580         __paint_subgraph <GT> (tgt_node, current_color);
01581 
01582             // cambiar color (siguiente arco que se visite pertenece a
01583             // otro bloque 
01584         current_color++; 
01585 
01586         I(not is_arc_painted <GT> (arc));
01587 
01588       }
01589   }
01639       template <typename GT> inline
01640   long paint_subgraphs(GT &                                 g, 
01641                        const DynDlist<typename GT::Node*> & cut_node_list)
01642   {
01643     g.reset_counter_nodes();
01644     g.reset_counter_arcs();
01645 
01646     long current_color = 1;
01647 
01648         // Recorrer cada nodo de corte y pintar sus bloques
01649     for (typename DynDlist<typename GT::Node*>::Iterator i(cut_node_list); 
01650          i.has_current(); i.next())
01651       __paint_from_cut_node <GT> (i.get_current(), current_color);
01652 
01653     return current_color;
01654   }
01655       template <typename GT> inline static
01656   void __map_subgraph(GT &                g,    // grafo con ptos de corte
01657                       GT &                sg,   // subgrafo donde se copia bloque
01658                       typename GT::Node * gsrc, // nodo de g ya copiado en sg
01659                       const long &        color)
01660   {
01661 
01662     I(get_color <GT> (gsrc) == color);
01663     I(NODE_COOKIE(gsrc) != NULL);
01664 
01665     typename GT::Node * tsrc = // obtener imagen de gsrc en sg
01666       static_cast<typename GT::Node*>(NODE_COOKIE(gsrc));
01667 
01668         // recorrer arcos de gsrc y añadir a sg aquellos con el color de interés
01669     for (typename GT::Node_Arc_Iterator i(gsrc); i.has_current(); i.next())
01670       {
01671         typename GT::Arc * garc = i.get_current_arc();
01672 
01673         if (get_color <GT> (garc) != color or IS_ARC_VISITED(garc, Build_Subtree))
01674           continue; // arco es de otro color o ya está visitado 
01675 
01676         ARC_BITS(garc).set_bit(Build_Subtree, true); // marque arco
01677 
01678         typename GT::Node * gtgt = i.get_tgt_node(); // nodo destino de garc
01679 
01680 
01681         I(get_color <GT> (gtgt) == color);
01682 
01683             // obtener imagen de gtgt en sg
01684         typename GT::Node * ttgt = NULL;
01685         if (IS_NODE_VISITED(gtgt, Build_Subtree)) // ¿gtgt ya está en sg?
01686           ttgt = static_cast<typename GT::Node*>(NODE_COOKIE(gtgt)); // sí
01687         else
01688           {     // gtgt no está en sg ==> copiarlo y mapearlo
01689             auto_ptr<typename GT::Node> 
01690               ttgt_auto ( new typename GT::Node (gtgt) );
01691 
01692             sg.insert_node(ttgt_auto.get());
01693             GT::map_nodes(gtgt, ttgt_auto.get());
01694 
01695             NODE_BITS(gtgt).set_bit(Build_Subtree, true); // marque gtgt
01696 
01697             ttgt = ttgt_auto.release(); 
01698           }
01699 
01700             // copiar y mapear arco en sg
01701         typename GT::Arc * tarc = sg.insert_arc(tsrc, ttgt, garc->get_info());
01702         GT::map_arcs(garc, tarc);
01703         
01704         __map_subgraph(g, sg, gtgt, color); // proseguir recursivamente con gtgt
01705       }
01706   }
01740       template <typename GT>
01741   void map_subgraph(GT & g, GT & sg, const long & color)
01742   {
01743     sg.clear_graph();
01744 
01745         // busque el primer nodo con el color
01746     typename GT::Node * first = NULL;
01747     for (typename GT::Node_Iterator it(g); it.has_current(); it.next())
01748       if (get_color <GT> (it.get_current_node()) == color)
01749         first = it.get_current_node();
01750 
01751     if (first == NULL) // Encontró el color?
01752       throw std::domain_error("Color does not exist in the graph");
01753 
01754 
01755         // cree first, insértelo en sg y mapéelo
01756     auto_ptr<typename GT::Node> auto_tsrc ( new typename GT::Node(first) );
01757     sg.insert_node(auto_tsrc.get());
01758     GT::map_nodes(first, auto_tsrc.release());
01759     NODE_BITS(first).set_bit(Build_Subtree, true); // márquelo visitado
01760 
01761 
01762     try
01763       {    
01764 
01765         __map_subgraph(g, sg, first, color); // mapee recursivamente desde first
01766 
01767       }
01768     catch (...)
01769       {
01770         sg.clear_graph();
01771       }
01772 
01773   }
01814       template <typename GT>
01815   void map_cut_graph(GT &                           g, 
01816                      DynDlist<typename GT::Node*> & cut_node_list,
01817                      GT &                           cut_graph,
01818                      DynDlist<typename GT::Arc*> &  cross_arc_list)
01819   {
01820     cut_graph.clear_graph();
01821 
01822         // recorra la lista de nodos de corte e insértelos en sg
01823     for (typename DynDlist<typename GT::Node*>::Iterator it(cut_node_list); 
01824          it.has_current(); it.next())
01825       {
01826         typename GT::Node * gp = it.get_current();
01827 
01828         I (is_a_cut_node <GT> (gp));
01829 
01830 
01831         auto_ptr<typename GT::Node> tp_auto ( new typename GT::Node(gp) );
01832 
01833         cut_graph.insert_node(tp_auto.get());
01834 
01835         GT::map_nodes(gp, tp_auto.release());
01836       }
01837 
01838         // Recorra los arcos; inserte en sg los que no sean de corte, en
01839         // cut_arc_list los que sean de corte y en cross_arc_list los que
01840         // sean de cruce    
01841     for (typename GT::Arc_Iterator it(g); it.has_current(); it.next())
01842       {
01843         typename GT::Arc * garc = it.get_current_arc();
01844 
01845         if (is_a_cross_arc <GT> (garc))
01846           {
01847             cross_arc_list.append(garc); 
01848             continue;
01849           }
01850 
01851         if (not is_an_cut_arc <GT> (garc))
01852           continue;
01853 
01854         typename GT::Node * src = 
01855           static_cast<typename GT::Node*>(NODE_COOKIE(g.get_src_node(garc)));
01856 
01857         typename GT::Node * tgt = 
01858           static_cast<typename GT::Node*>(NODE_COOKIE(g.get_tgt_node(garc)));
01859 
01860 
01861         I(src != NULL and tgt != NULL);
01862 
01863         typename GT::Arc * cut_arc = 
01864           cut_graph.insert_arc(src, tgt, garc->get_info());
01865 
01866         GT::map_arcs(garc, cut_arc);
01867       }
01868   }
01869     template <class GT, class Distance, class Compare> 
01870   struct Distance_Compare
01871   {
01872     bool operator () (typename GT::Arc * a1, typename GT::Arc * a2) const
01873     {
01874       return Compare () (Distance() (a1) , Distance() (a2) );
01875     }
01876   };
01877       template <class GT, class Distance, class Compare, class Plus>
01878   typename Distance::Distance_Type total_cost(GT & g)
01879   {
01880     typename Distance::Distance_Type sum = Distance::Zero_Distance;
01881 
01882         // recorrer todos los arcos y sumar su peso
01883     for (typename GT::Arc_Iterator it(g); it.has_current(); it.next())
01884       sum = Plus () (sum, Distance () (it.get_current_arc()));
01885 
01886     return sum;
01887   }
01888       template <class GT, class Distance>
01889   typename Distance::Distance_Type total_cost(GT & g)
01890   {
01891     typedef Aleph::less<typename Distance::Distance_Type> Less;
01892     typedef Aleph::plus<typename Distance::Distance_Type> Plus;
01893 
01894     return total_cost <GT, Distance, Less, Plus> (g);
01895   }
01896      template <class GT> static inline
01897   void __topological_sort(GT &                           g, 
01898                           typename GT::Node *            curr,
01899                           DynDlist<typename GT::Node*> & list)
01900   {
01901     if (IS_NODE_VISITED(curr, Depth_First)) 
01902       return;
01903 
01904     NODE_BITS(curr).set_bit(Depth_First, 1); // marcarlo como visitado
01905 
01906         // visitar recursivamente en sufijo los nodos adyacentes a curr
01907     for (typename GT::Arc_Node_Iterator it(g, curr); 
01908          it.has_current() and list.size() < g.get_num_nodes(); it.next()) 
01909       __topological_sort(g, it.get_tgt_node(), list);
01910     
01911     list.insert(curr); // inserción en sufijo de un nodo que devino sumidero
01912   }
01929      template <class GT> inline
01930   void topological_sort(GT & g, DynDlist<typename GT::Node*> & list)
01931   {
01932 
01933     if (not g.is_digraph())
01934       throw std::domain_error("g is not a digraph");
01935 
01936     g.reset_bit_nodes(Depth_First); // iniciar bit de marca de visita en nodos
01937 
01938     for (typename GT::Node_Iterator it(g); 
01939          it.has_current() and list.size() < g.get_num_nodes(); it.next())
01940       {
01941         typename GT::Node * curr = it.get_current_node();
01942 
01943         if (not IS_NODE_VISITED(curr, Depth_First))
01944           __topological_sort(g, curr, list);
01945       }
01946   }
01964      template <class GT> inline
01965   void q_topological_sort(GT & g, DynDlist<typename GT::Node*> & list)
01966   {
01967 
01968     if (not g.is_digraph())
01969       throw std::domain_error("g is not a digraph");
01970 
01971     g.reset_counter_nodes();
01972 
01973         // recorra todos los nodos para contabilizar su grado de entrada
01974     for (typename GT::Node_Iterator it(g); it.has_current(); it.next()) 
01975       NODE_COUNTER(it.get_current_node())++;
01976 
01977     DynListQueue<typename GT::Node*> q; // cola de fuentes
01978 
01979         // revisar cuáles nodos tienen grado de entrada 0; esos son fuente
01980     for (typename GT::Node_Iterator it(g); it.has_current(); it.next())
01981       {
01982         typename GT::Node * p = it.get_current_node();
01983 
01984         if (NODE_COUNTER(p) == 0) // ¿es un nodo fuente?
01985           q.put(p); // sí ==> colocarlo en la cola
01986       }
01987 
01988     while (not q.is_empty()) 
01989       {
01990         typename GT::Node * p = q.get(); // saque nodo fuente
01991 
01992         I(NODE_COUNTER(p) == 0);
01993 
01994         list.append(p); // insértelo en el orden topológico
01995 
01996             // decrementar grado de entrada de cada nodo adyacente a p
01997         for (typename GT::Node_Arc_Iterator it(g, p); it.has_current(); it.next())
01998           {
01999             typename GT::Node * tgt = it.get_tgt_node();
02000             
02001             if (--NODE_COUNTER(tgt) == 0) // ¿tgt deviene nodo fuente?
02002               q.put(tgt); // sí ==> colóquelo en la cola
02003           }
02004       }
02005   }
02006 
02007 } // end namespace Aleph
02008 
02009 # endif // TPL_GRAPH_UTILS_H
02010 

Leandro R. León