Recursivamente regresando al inicio Aleph-w: Algoritmos y estructuras de datos

Kruskal.H

00001 
00002 /*
00003   This file is part of Aleph-w system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
00006   Leandro Rabindranath León
00007   All rights reserved.
00008 
00009   Redistribution and use in source and binary forms, with or without
00010   modification, are permitted provided that the following conditions are
00011   met: 
00012   1. Redistributions of source code must retain the above copyright 
00013      notice, this list of conditions and the following disclaimer.
00014   2. Redistributions in binary form must reproduce the above copyright 
00015      notice, this list of conditions and the following disclaimer in the 
00016      documentation and/or other materials provided with the distribution.
00017   3. All advertising materials mentioning features or use of this software
00018      must display the following acknowledgement:
00019 
00020      Copyright (c) 2002-2011 Leandro Rabindranath León. See details of 
00021      licence.     
00022 
00023      This product includes software developed by the Hewlett-Packard
00024      Company, Free Software Foundation and Silicon Graphics Computer
00025      Systems, Inc. 
00026   4. Neither the name of the <organization> nor the
00027      names of its contributors may be used to endorse or promote products
00028      derived from this software without specific prior written permission.
00029 
00030 THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
00031 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00032 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00033 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00034 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00035 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00036 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00037 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00038 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00039 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00040 
00041   Aleph-w is distributed in the hope that it will be useful, but WITHOUT
00042   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00043   or FITNESS FOR A PARTICULAR PURPOSE.
00044 
00045   I request users of this software to return to 
00046 
00047   Leandro Rabindranath Leon
00048   CEMISID 
00049   Ed La Hechicera 
00050   3er piso, ala sur
00051   Facultad de Ingenieria 
00052   Universidad de Los Andes 
00053   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00054 
00055   lrleon@ula.ve
00056   leandro.r.leon@gmail.com
00057 
00058   any improvements or extensions that they make and grant me the rights
00059   to redistribute these changes.  
00060 */
00061 
00062 # ifndef KRUSKAL_H
00063 # define KRUSKAL_H
00064 
00065 # include <ahFunction.H>
00066 # include <tpl_graph.H>
00067 # include <tpl_graph_utils.H>
00068 # include <tpl_test_acyclique.H>
00069 
00070 using namespace Aleph;
00071 
00072 namespace Aleph {
00073 
00074   
00110  template <class GT, class Distance, 
00111        class Compare = Aleph::less<typename Distance::Distance_Type>, 
00112        class SA      = Default_Show_Arc<GT> > 
00113 class Kruskal_Min_Spanning_Tree 
00114 {
00115   Distance & dist;
00116   Compare &  cmp;
00117   SA      &  sa;
00118   
00119 public:
00120 
00127   Kruskal_Min_Spanning_Tree(Distance && __dist = Distance(),  
00128                 Compare &&  __cmp  = Compare(),
00129                 SA &&       __sa   = SA()) 
00130     : dist(__dist), cmp(__cmp), sa(__sa) 
00131   { 
00132     /* empty */ 
00133   }
00134 
00135   Kruskal_Min_Spanning_Tree(Distance & __dist, Compare &  __cmp, SA & __sa) 
00136     : dist(__dist), cmp(__cmp), sa(__sa)  
00137   { 
00138     /* empty */ 
00139   }
00140 
00141 private:
00142 
00143   void min_spanning_tree(GT & g, GT & tree)
00144   {
00145     if (g.is_digraph())
00146       throw std::domain_error("g is a digraph");
00147 
00148     g.reset_bit_nodes(Aleph::Kruskal); // limpiar bits de marcado
00149     clear_graph(tree); // limpia grafo destino 
00150 
00151     typedef Distance_Compare<GT, Distance, Compare> DCMP;
00152     DCMP comp(dist, cmp);
00153     g.template sort_arcs<DCMP>(comp);
00154 
00155         // Recorrer arcos ordenados de g hasta que numero de arcos de
00156         // tree sea igual al numero de nodos de g 
00157     for (Arc_Iterator<GT, SA> arc_itor(g, sa);       
00158      tree.get_num_arcs() < g.get_num_nodes() - 1; arc_itor.next()) 
00159       {     // obtenga siguiente menor arco
00160     typename GT::Arc * arc = arc_itor.get_current_arc();
00161 
00162     typename GT::Node * g_src_node = g.get_src_node(arc); // origen en g
00163     typename GT::Node * tree_src_node; // origen en tree
00164     if (not IS_NODE_VISITED(g_src_node, Aleph::Kruskal)) // ¿está en tree?
00165       { // No, crearlo en tree, atarlo al cookie y marcar como visitado
00166         NODE_BITS(g_src_node).set_bit(Aleph::Kruskal, true); 
00167         tree_src_node = tree.insert_node(g_src_node->get_info());
00168           GT::map_nodes(g_src_node, tree_src_node);
00169       }
00170     else
00171       tree_src_node = mapped_node<GT>(g_src_node);
00172 
00173     typename GT::Node * g_tgt_node = g.get_tgt_node(arc);
00174     typename GT::Node * tree_tgt_node; // destino en árbol abarcador
00175     if (not IS_NODE_VISITED(g_tgt_node, Aleph::Kruskal))
00176         { // No, crearlo en tree, atarlo al cookie y marcar como visitado
00177           NODE_BITS(g_tgt_node).set_bit(Aleph::Kruskal, true); 
00178           tree_tgt_node = tree.insert_node(g_tgt_node->get_info());
00179           GT::map_nodes(g_tgt_node, tree_tgt_node);
00180         }
00181     else
00182       tree_tgt_node = mapped_node<GT>(g_tgt_node);
00183 
00184     typename GT::Arc * arc_in_tree = 
00185       tree.insert_arc(tree_src_node, tree_tgt_node, arc->get_info());
00186 
00187     if (Has_Cycle<GT, SA> (sa) (tree)) // ¿arc_in_tree causa ciclo?
00188       {     // hay ciclo ==> hay que remover el arco
00189         tree.remove_arc(arc_in_tree); // eliminar arco y procesar 
00190         continue;                     // siguiente arco
00191       }
00192 
00193     GT::map_arcs(arc, arc_in_tree);
00194       }
00195   }
00196 
00197 public:
00198 
00210   void operator () (GT & g, GT & tree) 
00211   {
00212     min_spanning_tree (g, tree);
00213   }
00214 };
00215       
00216 
00217 } // end namespace Aleph
00218 
00219 # endif // KRUSKAL_H

Leandro Rabindranath León