jacint@173: // -*- C++ -*- jacint@173: /* jacint@211: *template > jacint@173: * jacint@173: *Constructor: jacint@173: * jacint@211: *Prim(Graph G, LengthMap weight) jacint@173: * jacint@173: * jacint@173: *Methods: jacint@173: * jacint@211: *void run() : Runs the Prim-algorithm from a random node jacint@173: * jacint@211: *void run(Node r) : Runs the Prim-algorithm from node s jacint@173: * jacint@211: *T weight() : After run(r) was run, it returns the minimum jacint@211: * weight of a spanning tree of the component of the root. jacint@173: * jacint@211: *Edge tree(Node v) : After run(r) was run, it returns the jacint@211: * first edge in the path from v to the root. Returns jacint@211: * INVALID if v=r or v is not reachable from the root. jacint@173: * jacint@211: *bool conn() : After run(r) was run, it is true iff G is connected jacint@173: * jacint@211: *bool reached(Node v) : After run(r) was run, it is true jacint@211: * iff v is in the same component as the root jacint@173: * jacint@211: *Node root() : returns the root jacint@173: * jacint@173: */ jacint@173: jacint@211: #ifndef HUGO_PRIM_H jacint@211: #define HUGO_PRIM_H jacint@173: jacint@173: #include jacint@211: #include jacint@173: jacint@173: namespace hugo { jacint@173: jacint@173: template >, jacint@211: typename LengthMap=typename Graph::EdgeMap > jacint@173: class Prim{ jacint@211: typedef typename Graph::Node Node; jacint@173: typedef typename Graph::NodeIt NodeIt; jacint@211: typedef typename Graph::Edge Edge; jacint@173: typedef typename Graph::OutEdgeIt OutEdgeIt; jacint@173: typedef typename Graph::InEdgeIt InEdgeIt; jacint@173: jacint@211: const Graph& G; jacint@211: const LengthMap& edge_weight; jacint@211: typename Graph::NodeMap tree_edge; jacint@173: typename Graph::NodeMap min_weight; jacint@211: typename Graph::NodeMap reach; jacint@173: jacint@173: public : jacint@173: jacint@211: Prim(Graph& _G, LengthMap& _edge_weight) : jacint@211: G(_G), edge_weight(_edge_weight), jacint@211: tree_edge(_G,INVALID), min_weight(_G), reach(_G, false) { } jacint@173: jacint@211: jacint@211: void run() { jacint@211: NodeIt _r; jacint@211: G.first(_r); jacint@211: run(_r); jacint@173: } jacint@173: jacint@173: jacint@211: void run(Node r) { jacint@211: jacint@211: NodeIt u; jacint@211: for ( G.first(u) ; G.valid(u) ; G.next(u) ) { jacint@211: tree_edge.set(u,INVALID); jacint@211: min_weight.set(u,0); jacint@211: reach.set(u,false); jacint@211: } jacint@211: jacint@173: jacint@173: typename Graph::NodeMap scanned(G, false); jacint@173: typename Graph::NodeMap heap_map(G,-1); jacint@173: jacint@173: Heap heap(heap_map); jacint@173: jacint@173: heap.push(r,0); jacint@211: reach.set(r, true); jacint@173: jacint@173: while ( !heap.empty() ) { jacint@173: jacint@211: Node v=heap.top(); jacint@173: min_weight.set(v, heap.get(v)); jacint@173: heap.pop(); jacint@173: scanned.set(v,true); jacint@173: jacint@173: OutEdgeIt e; jacint@211: for( G.first(e,v); G.valid(e); G.next(e)) { jacint@211: Node w=G.head(e); jacint@173: jacint@211: if ( !scanned[w] ) { jacint@211: if ( !reach[w] ) { jacint@211: reach.set(w,true); jacint@211: heap.push(w, edge_weight[e]); jacint@173: tree_edge.set(w,e); jacint@211: } else if ( edge_weight[e] < heap.get(w) ) { jacint@173: tree_edge.set(w,e); jacint@211: heap.decrease(w, edge_weight[e]); jacint@173: } jacint@173: } jacint@173: } jacint@173: jacint@173: InEdgeIt f; jacint@211: for( G.first(f,v); G.valid(f); G.next(f)) { jacint@211: Node w=G.tail(f); jacint@173: jacint@211: if ( !scanned[w] ) { jacint@211: if ( !reach[w] ) { jacint@211: reach.set(w,true); jacint@211: heap.push(w, edge_weight[f]); jacint@173: tree_edge.set(w,f); jacint@211: } else if ( edge_weight[f] < heap.get(w) ) { jacint@173: tree_edge.set(w,f); jacint@211: heap.decrease(w, edge_weight[f]); jacint@173: } jacint@173: } jacint@173: } jacint@173: } jacint@173: } jacint@173: jacint@173: jacint@173: T weight() { jacint@173: T w=0; jacint@211: NodeIt u; jacint@211: for ( G.first(u) ; G.valid(u) ; G.next(u) ) w+=min_weight[u]; jacint@173: return w; jacint@173: } jacint@173: jacint@173: jacint@211: Edge tree(Node v) { jacint@211: return tree_edge[v]; jacint@173: } jacint@173: jacint@173: jacint@173: bool conn() { jacint@173: bool c=true; jacint@211: NodeIt u; jacint@211: for ( G.first(u) ; G.valid(u) ; G.next(u) ) jacint@211: if ( !reached[u] ) { jacint@173: c=false; jacint@173: break; jacint@173: } jacint@173: return c; jacint@173: } jacint@173: jacint@173: jacint@211: bool reached(Node v) { jacint@211: return reached[v]; jacint@173: } jacint@173: jacint@173: jacint@211: Node root() { jacint@173: return r; jacint@173: } jacint@173: jacint@173: }; jacint@173: jacint@173: } jacint@173: jacint@173: #endif jacint@173: jacint@173: