Kruskal.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 # ifndef KRUSKAL_H
00044 # define KRUSKAL_H
00045 
00046 # include <ahFunction.H>
00047 # include <tpl_graph.H>
00048 # include <tpl_graph_utils.H>
00049 
00050 using namespace Aleph;
00051 
00052 namespace Aleph {
00053 
00103     template <class GT, class Distance, class Compare> inline 
00104 void kruskal_min_spanning_tree(GT & g, GT & tree)
00105 {
00106 
00107   if (g.is_digraph())
00108     throw std::domain_error("g is a digraph");
00109 
00110   if (not test_connectivity(g))
00111     throw std::invalid_argument("Input graph is not connected");
00112 
00113   g.reset_bit_nodes(Aleph::Kruskal); // limpiar bits de marcado
00114 
00115   tree.clear_graph(); // limpia grafo destino 
00116 
00117   g.template sort_arcs<Distance_Compare<GT, Distance, Compare> >();
00118     // Recorrer arcos ordenados de g hasta que numero de arcos de tree sea
00119     // igual a numero de nodos de g 
00120   for (typename GT::Arc_Iterator arc_itor(g);       
00121        tree.get_num_arcs() < g.get_num_nodes() - 1; arc_itor.next()) 
00122     {     // obtenga siguiente menor arco
00123       typename GT::Arc * arc = arc_itor.get_current_arc();
00124 
00125       typename GT::Node * g_src_node = g.get_src_node(arc); // nodo origen en g
00126 
00127       typename GT::Node * tree_src_node; // nodo origen en tree
00128 
00129       if (not IS_NODE_VISITED(g_src_node, Aleph::Kruskal)) // ¿está en tree?
00130         {     // No, crearlo en tree, atarlo al cookie y marcar como visitado
00131           NODE_BITS(g_src_node).set_bit(Aleph::Kruskal, true); 
00132           tree_src_node = tree.insert_node(g_src_node->get_info());
00133           GT::map_nodes(g_src_node, tree_src_node);
00134         }
00135        else
00136          tree_src_node = static_cast<typename GT::Node*>(NODE_COOKIE(g_src_node));
00137       typename GT::Node * g_tgt_node = g.get_tgt_node(arc);
00138       typename GT::Node * tree_tgt_node; // Nodo destino en árbol abarcador
00139       if (not IS_NODE_VISITED(g_tgt_node, Aleph::Kruskal))
00140         {     // No, crearlo en tree, atarlo al cookie y marcar como visitado
00141           NODE_BITS(g_tgt_node).set_bit(Aleph::Kruskal, true); 
00142           tree_tgt_node = tree.insert_node(g_tgt_node->get_info());
00143           GT::map_nodes(g_tgt_node, tree_tgt_node);
00144         }
00145        else
00146          tree_tgt_node = static_cast<typename GT::Node*>(NODE_COOKIE(g_tgt_node));
00147 
00148       typename GT::Arc * arc_in_tree = 
00149         tree.insert_arc(tree_src_node, tree_tgt_node, arc->get_info());
00150 
00151       if (has_cycle(tree)) // verifique si nuevo arco causa un ciclo
00152         {     // hay ciclo ==> hay que remover el arco
00153           tree.remove_arc(arc_in_tree); // eliminar arco e ir a procesar 
00154           continue;                     // siguiente arco
00155         }
00156       GT::map_arcs(arc, arc_in_tree);
00157     }
00158 }
00159 
00160     template <class GT, class Distance> inline 
00161 void kruskal_min_spanning_tree(GT & g, GT & tree)
00162 {
00163   typedef typename Distance::Distance_Type DT;
00164 
00165   kruskal_min_spanning_tree<GT, Distance, Aleph::less<DT> > (g, tree);
00166 }
00167 
00168 
00169 } // end namespace Aleph
00170 
00171 # endif // KRUSKAL_H

Leandro R. León