Usage of any sort of pointer to access the inner workings of a std::priority_queue
to update an element within is problematic. In a minimum priority queue, for instance, the data structure guarantees that the value of the node is smaller than that of its children. If you choose to update the value within the priority queue, you would have to do the bubble up operation manually in order to preserve the integrity of that guarantee. Doing bubble up/down operations manually sort of beats the point of using a collection like std::priority_queue
.
Using a std::set
offers a viable alternative. To retrieve the minimum and maximum, you can simply use the begin
and rbegin
pointers of the set. Aside from the set, you should keep an array/vector (i.e. random access collection) of minimum distances M
for the nodes. Whenever your relaxation yields a shorter path to a node v
, you may delete the old set entry of v
, update M[v]
, and insert the entry of v
to the set with the new M[v]
value. Updating M[v]
is done in constant time, and set operations take O(log|V|)
time. So, even though it has a greater constant factor than priority queue, using a set has the same asymptotic complexity.
Below is a pseudocode illustrating the usage. Since your code was incomplete, I resorted to using standard datatypes. Vertices of the graph are 0-indexed, and for vi, the adjacency list adjList
keeps a vector of outgoing edges in adjList[i]
. For each edge, the index of the destination vertex and the weight of that edge are kept, respectively.
void dijkstra(vector< vector< pair<int, long long> > >& adjList, int source) {
set< pair<long long, int> > priorityQueue;
vector< long long > minCosts(adjList.size(), INFINITY);
minCosts[source] = 0LL;
priorityQueue.insert( make_pair(minCosts[source], source) );
while(!priorityQueue.empty()) {
set< pair<long long, int> >::iterator it = priorityQueue.begin();
int u = it->second;
long long costU = it->first;
for(int i=0; i < adjList[u].size(); ++i) {
int v = adjList[u][i].first;
long long w = adjList[u][i].second;
if (costU + w < minCosts[v]) {
if(minCosts[v] < INFINITY) {
priorityQueue.erase( make_pair(minCosts[v], v) );
}
minCosts[v] = costU + w;
priorityQueue.insert( make_pair(minCosts[v], v) );
}
}
}
// minCosts[] now keeps the minimal distance of all nodes from source
}
Obviously, the retrieval of edge costs and relevant adjacency list entries may be different in your codebase, but since you did not provide those details, I tried to provide a more generic code sample that could minimally emphasize the point. Basically, the set may just keep a pair of cost and node index, respectively, and you're all set.
Alternatively, you may define a comparison operator for vehicleNode
type and just keep that inside the set, as opposed to a pair of cost & node. But that is just an implementation-specific decision, and not the main point of your question.