I have implemented Dijkstra algorithm to perform Shortest Path problem.
Input:
Adjacency List(Directed Graph): Description is like that
{Source Node, {edge_1, .. , edge_N}}
Cost Matrix (Same format as Adjacency List)
Queue: Priority Queue
Input to "Shortest Path" method are Start Node, End Node; it returns -1 if there is no path from Source Node to Target Node, else it returns the cost of the minimum path selected.
Code:
#include <algorithm>
#include <iostream>
#include <limits>
#include <queue>
#include <tuple>
#include <unordered_map>
#include <vector>
namespace {
constexpr int ZERO_DISTANCE_VALUE = 0;
constexpr int INFINITY_VALUE = std::numeric_limits<int>::max();
} // namespace
using NodeType = int;
using CostType = int;
using AdjacencyListType = std::vector<std::vector<NodeType>>;
using DistanceVector = std::vector<NodeType>;
using QueueType = std::queue<NodeType>;
using CostEdgeVector = std::vector<std::vector<CostType>>;
using CostNodeTuple = std::tuple<NodeType, CostType>;
using DistanceMatrixType = std::vector<CostType>;
class Graph {
public:
explicit Graph(const AdjacencyListType &input_list,
const CostEdgeVector &input_cost_list)
: adjancecy_list(input_list), cost_list(input_cost_list) {}
struct QueueComparator {
bool operator()(const CostNodeTuple &left, const CostNodeTuple &right) {
return std::get<1>(left) < std::get<1>(right);
}
};
int shortest_path(const int &source, const int &target) {
int result = 0;
if (source == target)
return result;
if (!is_valid_node(source))
return -1;
std::vector<int> distance_node(adjancecy_list.size(), INFINITY_VALUE);
distance_node[source] = 0;
queue.emplace(std::make_tuple(source, 0));
while (!queue.empty()) {
const auto ¤t_node = queue.top();
queue.pop();
const NodeType ¤t_node_index = std::get<0>(current_node);
const auto &sub_node_vector = adjancecy_list.at(current_node_index);
const auto &sub_node_cost = cost_list.at(current_node_index);
const int ¤t_distance_cost = distance_node.at(current_node_index);
for (NodeType index = 0; index < sub_node_vector.size(); ++index) {
const auto &child_index = sub_node_vector.at(index);
const int relaxation_value =
current_distance_cost + sub_node_cost.at(index);
if ((distance_node.at(child_index) > relaxation_value)) {
distance_node[child_index] = relaxation_value;
queue.emplace(std::make_tuple(child_index, relaxation_value));
}
}
}
try {
const auto &target_distance = distance_node.at(target);
result = target_distance == INFINITY_VALUE ? -1 : target_distance;
} catch (...) {
result = -1;
}
return result;
}
private:
bool is_valid_node(const NodeType &node) {
return node < adjancecy_list.size();
}
std::priority_queue<std::tuple<NodeType, int>,
std::vector<std::tuple<NodeType, int>>, QueueComparator>
queue;
const CostEdgeVector &cost_list;
const AdjacencyListType &adjancecy_list;
};
int main() {
AdjacencyListType cost_vector;
CostEdgeVector adjancecy_list;
NodeType source_node = 0;
NodeType target_node = 0;
Graph graph(adjancecy_list, cost_vector);
const auto result = graph.shortest_path(source_node, target_node);
std::cout << "Shortest Path value: " << result << std::endl;
return 0;
}