alpar@222: // -*- C++ -*- alpar@222: /* alpar@222: *template > alpar@222: * alpar@222: *Constructor: alpar@222: * alpar@222: *Dijkstra(Graph G, LengthMap length) alpar@222: * alpar@222: * alpar@222: *Methods: alpar@222: * alpar@222: *void run(Node s) alpar@222: * alpar@222: *T dist(Node v) : After run(s) was run, it returns the distance from s to v. alpar@222: * Returns T() if v is not reachable from s. alpar@222: * alpar@222: *Edge pred(Node v) : After run(s) was run, it returns the last alpar@222: * edge of a shortest s-v path. It is INVALID for s and for alpar@222: * the nodes not reachable from s. alpar@222: * alpar@222: *bool reached(Node v) : After run(s) was run, it is true iff v is alpar@222: * reachable from s alpar@222: * alpar@222: */ alpar@222: alpar@222: #ifndef HUGO_DIJKSTRA_H alpar@222: #define HUGO_DIJKSTRA_H alpar@222: alpar@222: #include alpar@222: #include alpar@222: alpar@222: namespace hugo { alpar@222: alpar@222: //Alpar: Changed the order of the parameters alpar@222: template , alpar@222: typename Heap=FibHeap > > alpar@222: class Dijkstra{ alpar@222: public: alpar@222: typedef typename LengthMap::ValueType ValueType; alpar@222: alpar@222: private: alpar@222: typedef typename Graph::Node Node; alpar@222: typedef typename Graph::NodeIt NodeIt; alpar@222: typedef typename Graph::Edge Edge; alpar@222: typedef typename Graph::OutEdgeIt OutEdgeIt; alpar@222: alpar@222: const Graph& G; alpar@222: const LengthMap& length; alpar@222: typedef typename Graph::NodeMap PredMap; alpar@222: PredMap predecessor; alpar@222: //In place of reach: alpar@222: typedef typename Graph::NodeMap PredNodeMap; alpar@222: PredNodeMap pred_node; alpar@222: typedef typename Graph::NodeMap DistMap; alpar@222: DistMap distance; alpar@222: //I don't like this: alpar@222: // //FIXME: alpar@222: // typename Graph::NodeMap reach; alpar@222: // //typename Graph::NodeMap reach; alpar@222: alpar@222: public : alpar@222: alpar@222: /* alpar@222: The distance of the nodes is 0. alpar@222: */ alpar@222: Dijkstra(Graph& _G, LengthMap& _length) : alpar@222: G(_G), length(_length), predecessor(_G), pred_node(_G), distance(_G) { } alpar@222: alpar@222: alpar@222: void run(Node s); alpar@222: alpar@222: ValueType dist(Node v) const { return distance[v]; } alpar@222: Edge pred(Node v) const { return predecessor[v]; } alpar@222: Node predNode(Node v) const { return pred_node[v]; } alpar@222: alpar@222: const DistMap &distMap() const { return distance;} alpar@222: const PredMap &predMap() const { return predecessor;} alpar@222: const PredNodeMap &predNodeMap() const { return pred_node;} alpar@222: alpar@222: // bool reached(Node v) { return reach[v]; } alpar@222: ///\warning \c s is not reached! alpar@222: /// alpar@222: bool reached(Node v) { return G.valid(predecessor[v]); } alpar@222: alpar@222: }; alpar@222: alpar@222: alpar@222: // IMPLEMENTATIONS alpar@222: alpar@222: template alpar@222: void Dijkstra::run(Node s) { alpar@222: alpar@222: NodeIt u; alpar@222: for ( G.first(u) ; G.valid(u) ; G.next(u) ) { alpar@222: predecessor.set(u,INVALID); alpar@222: // If a node is unreacheable, then why should be the dist=0? alpar@222: // distance.set(u,0); alpar@222: // reach.set(u,false); alpar@222: } alpar@222: alpar@222: //We don't need it at all. alpar@222: // //FIXME: alpar@222: // typename Graph::NodeMap scanned(G,false); alpar@222: // //typename Graph::NodeMap scanned(G,false); alpar@222: typename Graph::NodeMap heap_map(G,-1); alpar@222: alpar@222: Heap heap(heap_map); alpar@222: alpar@222: heap.push(s,0); alpar@222: // reach.set(s, true); alpar@222: alpar@222: while ( !heap.empty() ) { alpar@222: alpar@222: Node v=heap.top(); alpar@222: ValueType oldvalue=heap[v]; alpar@222: heap.pop(); alpar@222: distance.set(v, oldvalue); alpar@222: alpar@222: for(OutEdgeIt e(G,v); G.valid(e); G.next(e)) { alpar@222: Node w=G.head(e); alpar@222: alpar@222: switch(heap.state(w)) { alpar@222: case Heap::PRE_HEAP: alpar@222: // reach.set(w,true); alpar@222: heap.push(w,oldvalue+length[e]); alpar@222: predecessor.set(w,e); alpar@222: pred_node.set(w,v); alpar@222: break; alpar@222: case Heap::IN_HEAP: alpar@222: if ( oldvalue+length[e] < heap[w] ) { alpar@222: heap.decrease(w, oldvalue+length[e]); alpar@222: predecessor.set(w,e); alpar@222: pred_node.set(w,v); alpar@222: } alpar@222: break; alpar@222: case Heap::POST_HEAP: alpar@222: break; alpar@222: } alpar@222: } alpar@222: } alpar@222: } alpar@222: alpar@222: } //END OF NAMESPACE HUGO alpar@222: alpar@222: #endif alpar@222: alpar@222: