Algorithms_in_C++ 1.0.0
Set of algorithms implemented in C++.
Loading...
Searching...
No Matches
bidirectional_dijkstra.cpp File Reference

[Bidirectional Dijkstra Shortest Path Algorithm] (https://www.coursera.org/learn/algorithms-on-graphs/lecture/7ml18/bidirectional-dijkstra) More...

#include <cassert>
#include <iostream>
#include <limits>
#include <queue>
#include <utility>
#include <vector>
Include dependency graph for bidirectional_dijkstra.cpp:

Namespaces

namespace  graph
 Graph Algorithms.
 
namespace  bidirectional_dijkstra
 Functions for [Bidirectional Dijkstra Shortest Path] (https://www.coursera.org/learn/algorithms-on-graphs/lecture/7ml18/bidirectional-dijkstra) algorithm.
 

Functions

void graph::bidirectional_dijkstra::addEdge (std::vector< std::vector< std::pair< uint64_t, uint64_t > > > *adj1, std::vector< std::vector< std::pair< uint64_t, uint64_t > > > *adj2, uint64_t u, uint64_t v, uint64_t w)
 Function that add edge between two nodes or vertices of graph.
 
uint64_t graph::bidirectional_dijkstra::Shortest_Path_Distance (const std::vector< uint64_t > &workset_, const std::vector< std::vector< uint64_t > > &distance_)
 This function returns the shortest distance from the source to the target if there is path between vertices 's' and 't'.
 
int graph::bidirectional_dijkstra::Bidijkstra (std::vector< std::vector< std::pair< uint64_t, uint64_t > > > *adj1, std::vector< std::vector< std::pair< uint64_t, uint64_t > > > *adj2, uint64_t s, uint64_t t)
 Function runs the dijkstra algorithm for some source vertex and target vertex in the graph and returns the shortest distance of target from the source.
 
static void tests ()
 Function to test the provided algorithm above.
 
int main ()
 Main function.
 

Variables

constexpr int64_t INF = std::numeric_limits<int64_t>::max()
 for store the graph, the distances, and the path
 

Detailed Description

[Bidirectional Dijkstra Shortest Path Algorithm] (https://www.coursera.org/learn/algorithms-on-graphs/lecture/7ml18/bidirectional-dijkstra)

Author
Marinovksy

This is basically the same Dijkstra Algorithm but faster because it goes from the source to the target and from target to the source and stops when finding a vertex visited already by the direct search or the reverse one. Here some simulations of it: https://www.youtube.com/watch?v=DINCL5cd_w0&t=24s

Function Documentation

◆ addEdge()

void graph::bidirectional_dijkstra::addEdge ( std::vector< std::vector< std::pair< uint64_t, uint64_t > > > * adj1,
std::vector< std::vector< std::pair< uint64_t, uint64_t > > > * adj2,
uint64_t u,
uint64_t v,
uint64_t w )

Function that add edge between two nodes or vertices of graph.

Parameters
adj1adjacency list for the direct search
adj2adjacency list for the reverse search
uany node or vertex of graph
vany node or vertex of graph
47 {
48 (*adj1)[u - 1].push_back(std::make_pair(v - 1, w));
49 (*adj2)[v - 1].push_back(std::make_pair(u - 1, w));
50 // (*adj)[v - 1].push_back(std::make_pair(u - 1, w));
51}
T make_pair(T... args)
Here is the call graph for this function:

◆ Bidijkstra()

int graph::bidirectional_dijkstra::Bidijkstra ( std::vector< std::vector< std::pair< uint64_t, uint64_t > > > * adj1,
std::vector< std::vector< std::pair< uint64_t, uint64_t > > > * adj2,
uint64_t s,
uint64_t t )

Function runs the dijkstra algorithm for some source vertex and target vertex in the graph and returns the shortest distance of target from the source.

Parameters
adj1input graph
adj2input graph reversed
ssource vertex
ttarget vertex
Returns
shortest distance if target is reachable from source else -1 in case if target is not reachable from source.

n denotes the number of vertices in graph

setting all the distances initially to INF

creating a a vector of min heap using priority queue pq[0] contains the min heap for the direct search pq[1] contains the min heap for the reverse search

first element of pair contains the distance second element of pair contains the vertex

vector for store the nodes or vertices in the shortest path

vector for store the nodes or vertices visited

pushing the source vertex 's' with 0 distance in pq[0] min heap

marking the distance of source as 0

pushing the target vertex 't' with 0 distance in pq[1] min heap

marking the distance of target as 0

direct search

second element of pair denotes the node / vertex

first element of pair denotes the distance

for all the reachable vertex from the currently exploring vertex we will try to minimize the distance

minimizing distances

check if currentNode has already been visited

reversed search

second element of pair denotes the node / vertex

first element of pair denotes the distance

for all the reachable vertex from the currently exploring vertex we will try to minimize the distance

minimizing distances

check if currentNode has already been visited

88 {
89 /// n denotes the number of vertices in graph
90 uint64_t n = adj1->size();
91
92 /// setting all the distances initially to INF
94
95 /// creating a a vector of min heap using priority queue
96 /// pq[0] contains the min heap for the direct search
97 /// pq[1] contains the min heap for the reverse search
98
99 /// first element of pair contains the distance
100 /// second element of pair contains the vertex
105 pq(2);
106 /// vector for store the nodes or vertices in the shortest path
107 std::vector<uint64_t> workset(n);
108 /// vector for store the nodes or vertices visited
109 std::vector<bool> visited(n);
110
111 /// pushing the source vertex 's' with 0 distance in pq[0] min heap
112 pq[0].push(std::make_pair(0, s));
113
114 /// marking the distance of source as 0
115 dist[0][s] = 0;
116
117 /// pushing the target vertex 't' with 0 distance in pq[1] min heap
118 pq[1].push(std::make_pair(0, t));
119
120 /// marking the distance of target as 0
121 dist[1][t] = 0;
122
123 while (true) {
124 /// direct search
125
126 // If pq[0].size() is equal to zero then the node/ vertex is not
127 // reachable from s
128 if (pq[0].size() == 0) {
129 break;
130 }
131 /// second element of pair denotes the node / vertex
132 uint64_t currentNode = pq[0].top().second;
133
134 /// first element of pair denotes the distance
135 uint64_t currentDist = pq[0].top().first;
136
137 pq[0].pop();
138
139 /// for all the reachable vertex from the currently exploring vertex
140 /// we will try to minimize the distance
141 for (std::pair<int, int> edge : (*adj1)[currentNode]) {
142 /// minimizing distances
143 if (currentDist + edge.second < dist[0][edge.first]) {
144 dist[0][edge.first] = currentDist + edge.second;
145 pq[0].push(std::make_pair(dist[0][edge.first], edge.first));
146 }
147 }
148 // store the processed node/ vertex
149 workset.push_back(currentNode);
150
151 /// check if currentNode has already been visited
152 if (visited[currentNode] == 1) {
153 return Shortest_Path_Distance(workset, dist);
154 }
155 visited[currentNode] = true;
156 /// reversed search
157
158 // If pq[1].size() is equal to zero then the node/ vertex is not
159 // reachable from t
160 if (pq[1].size() == 0) {
161 break;
162 }
163 /// second element of pair denotes the node / vertex
164 currentNode = pq[1].top().second;
165
166 /// first element of pair denotes the distance
167 currentDist = pq[1].top().first;
168
169 pq[1].pop();
170
171 /// for all the reachable vertex from the currently exploring vertex
172 /// we will try to minimize the distance
173 for (std::pair<int, int> edge : (*adj2)[currentNode]) {
174 /// minimizing distances
175 if (currentDist + edge.second < dist[1][edge.first]) {
176 dist[1][edge.first] = currentDist + edge.second;
177 pq[1].push(std::make_pair(dist[1][edge.first], edge.first));
178 }
179 }
180 // store the processed node/ vertex
181 workset.push_back(currentNode);
182
183 /// check if currentNode has already been visited
184 if (visited[currentNode] == 1) {
185 return Shortest_Path_Distance(workset, dist);
186 }
187 visited[currentNode] = true;
188 }
189 return -1;
190}
uint64_t Shortest_Path_Distance(const std::vector< uint64_t > &workset_, const std::vector< std::vector< uint64_t > > &distance_)
This function returns the shortest distance from the source to the target if there is path between ve...
Definition bidirectional_dijkstra.cpp:61
constexpr int64_t INF
for store the graph, the distances, and the path
Definition bidirectional_dijkstra.cpp:23
T size(T... args)
Here is the call graph for this function:

◆ main()

int main ( void )

Main function.

Returns
0 on exit
248 {
249 tests(); // running predefined tests
250 uint64_t vertices = uint64_t();
251 uint64_t edges = uint64_t();
252 std::cout << "Enter the number of vertices : ";
253 std::cin >> vertices;
254 std::cout << "Enter the number of edges : ";
255 std::cin >> edges;
256
261
262 uint64_t u = uint64_t(), v = uint64_t(), w = uint64_t();
263 std::cout << "Enter the edges by three integers in this form: u v w "
264 << std::endl;
265 std::cout << "Example: if there is and edge between node 1 and node 4 with "
266 "weight 7 enter: 1 4 7, and then press enter"
267 << std::endl;
268 while (edges--) {
269 std::cin >> u >> v >> w;
270 graph::bidirectional_dijkstra::addEdge(&adj1, &adj2, u, v, w);
271 if (edges != 0) {
272 std::cout << "Enter the next edge" << std::endl;
273 }
274 }
275
276 uint64_t s = uint64_t(), t = uint64_t();
278 << "Enter the source node and the target node separated by a space"
279 << std::endl;
280 std::cout << "Example: If the source node is 5 and the target node is 6 "
281 "enter: 5 6 and press enter"
282 << std::endl;
283 std::cin >> s >> t;
284 int dist =
285 graph::bidirectional_dijkstra::Bidijkstra(&adj1, &adj2, s - 1, t - 1);
286 if (dist == -1) {
287 std::cout << "Target not reachable from source" << std::endl;
288 } else {
289 std::cout << "Shortest Path Distance : " << dist << std::endl;
290 }
291
292 return 0;
293}
int Bidijkstra(std::vector< std::vector< std::pair< uint64_t, uint64_t > > > *adj1, std::vector< std::vector< std::pair< uint64_t, uint64_t > > > *adj2, uint64_t s, uint64_t t)
Function runs the dijkstra algorithm for some source vertex and target vertex in the graph and return...
Definition bidirectional_dijkstra.cpp:86
static void tests()
Function to test the provided algorithm above.
Definition bidirectional_dijkstra.cpp:199
void addEdge(std::vector< std::vector< std::pair< uint64_t, uint64_t > > > *adj1, std::vector< std::vector< std::pair< uint64_t, uint64_t > > > *adj2, uint64_t u, uint64_t v, uint64_t w)
Function that add edge between two nodes or vertices of graph.
Definition bidirectional_dijkstra.cpp:45
T endl(T... args)
Here is the call graph for this function:

◆ Shortest_Path_Distance()

uint64_t graph::bidirectional_dijkstra::Shortest_Path_Distance ( const std::vector< uint64_t > & workset_,
const std::vector< std::vector< uint64_t > > & distance_ )

This function returns the shortest distance from the source to the target if there is path between vertices 's' and 't'.

Parameters
workset_vertices visited in the search
distance_vector of distances from the source to the target and from the target to the source
63 {
64 int64_t distance = INF;
65 for (uint64_t i : workset_) {
66 if (distance_[0][i] + distance_[1][i] < distance) {
67 distance = distance_[0][i] + distance_[1][i];
68 }
69 }
70 return distance;
71}
T distance(T... args)
Here is the call graph for this function:

◆ tests()

static void tests ( )
static

Function to test the provided algorithm above.

Returns
void
199 {
200 std::cout << "Initiatinig Predefined Tests..." << std::endl;
201 std::cout << "Initiating Test 1..." << std::endl;
206 graph::bidirectional_dijkstra::addEdge(&adj1_1, &adj1_2, 1, 2, 1);
207 graph::bidirectional_dijkstra::addEdge(&adj1_1, &adj1_2, 4, 1, 2);
208 graph::bidirectional_dijkstra::addEdge(&adj1_1, &adj1_2, 2, 3, 2);
209 graph::bidirectional_dijkstra::addEdge(&adj1_1, &adj1_2, 1, 3, 5);
210
211 uint64_t s = 1, t = 3;
212 assert(graph::bidirectional_dijkstra::Bidijkstra(&adj1_1, &adj1_2, s - 1,
213 t - 1) == 3);
214 std::cout << "Test 1 Passed..." << std::endl;
215
216 s = 4, t = 3;
217 std::cout << "Initiating Test 2..." << std::endl;
218 assert(graph::bidirectional_dijkstra::Bidijkstra(&adj1_1, &adj1_2, s - 1,
219 t - 1) == 5);
220 std::cout << "Test 2 Passed..." << std::endl;
221
226 graph::bidirectional_dijkstra::addEdge(&adj2_1, &adj2_2, 1, 2, 4);
227 graph::bidirectional_dijkstra::addEdge(&adj2_1, &adj2_2, 1, 3, 2);
228 graph::bidirectional_dijkstra::addEdge(&adj2_1, &adj2_2, 2, 3, 2);
229 graph::bidirectional_dijkstra::addEdge(&adj2_1, &adj2_2, 3, 2, 1);
230 graph::bidirectional_dijkstra::addEdge(&adj2_1, &adj2_2, 2, 4, 2);
231 graph::bidirectional_dijkstra::addEdge(&adj2_1, &adj2_2, 3, 5, 4);
232 graph::bidirectional_dijkstra::addEdge(&adj2_1, &adj2_2, 5, 4, 1);
233 graph::bidirectional_dijkstra::addEdge(&adj2_1, &adj2_2, 2, 5, 3);
234 graph::bidirectional_dijkstra::addEdge(&adj2_1, &adj2_2, 3, 4, 4);
235
236 s = 1, t = 5;
237 std::cout << "Initiating Test 3..." << std::endl;
238 assert(graph::bidirectional_dijkstra::Bidijkstra(&adj2_1, &adj2_2, s - 1,
239 t - 1) == 6);
240 std::cout << "Test 3 Passed..." << std::endl;
241 std::cout << "All Test Passed..." << std::endl << std::endl;
242}
Here is the call graph for this function:

Variable Documentation

◆ INF

constexpr int64_t INF = std::numeric_limits<int64_t>::max()
constexpr

for store the graph, the distances, and the path

for assert for io operations for variable INF for the priority_queue of distances for make_pair function