Dijkstra’s Algorithm to find Shortest Paths from a Source to all
Given a weighted undirected graph represented as an edge list and a source vertex src
, find the shortest path distances from the source vertex to all other vertices in the graph. The graph contains V
vertices, numbered from 0
to V - 1
.
Note: The given graph does not contain any negative edge.
Examples:
Input: src = 0, V = 5, edges[][] = [[0, 1, 4], [0, 2, 8], [1, 4, 6], [2, 3, 2], [3, 4, 10]]
Graph with 5 node
Output: 0 4 8 10 10
Explanation: Shortest Paths:
0 to 1 = 4. 0 → 1
0 to 2 = 8. 0 → 2
0 to 3 = 10. 0 → 2 → 3
0 to 4 = 10. 0 → 1 → 4
Dijkstra’s Algorithm using Min Heap – O(E*logV) Time and O(V) Space
In Dijkstra’s Algorithm, the goal is to find the shortest distance from a given source node to all other nodes in the graph. As the source node is the starting point, its distance is initialized to zero. From there, we iteratively pick the unprocessed node with the minimum distance from the source, this is where a min-heap (priority queue) or a set is typically used for efficiency. For each picked node u, we update the distance to its neighbors v using the formula: dist[v] = dist[u] + weight[u][v], but only if this new path offers a shorter distance than the current known one. This process continues until all nodes have been processed.
For a deeper understanding of Dijkstra’s algorithm, refer to this resource.
Step-by-Step Implementation
- Set
dist=0
and all other distances asinfinity
. - Push the source node into the min heap as a pair
<distance, node>
→ i.e.,<0, source>
. - Pop the top element (node with the smallest distance).
- For each adjacent neighbor of the current node:
- Calculate the distance using the formula:
dist[v] = dist[u] + weight[u][v]
If this new distance is shorter than the currentdist[v]
, update it.
Push the updated pair<dist[v], v>
into the min heap
- Repeat step 3 until the min heap is empty.
- Return the distance array, which holds the shortest distance from the source to all nodes.
Illustration:
//Driver Code Starts{
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
// Function to construct adjacency
vector<vector<vector<int>>> constructAdj(vector<vector<int>>
&edges, int V) {
// adj[u] = list of {v, wt}
vector<vector<vector<int>>> adj(V);
for (const auto &edge : edges) {
int u = edge[0];
int v = edge[1];
int wt = edge[2];
adj[u].push_back({v, wt});
adj[v].push_back({u, wt});
}
return adj;
}
//Driver Code Ends }
// Returns shortest distances from src to all other vertices
vector<int> dijkstra(int V, vector<vector<int>> &edges, int src){
// Create adjacency list
vector<vector<vector<int>>> adj = constructAdj(edges, V);
// Create a priority queue to store vertices that
// are being preprocessed.
priority_queue<vector<int>, vector<vector<int>>,
greater<vector<int>>> pq;
// Create a vector for distances and initialize all
// distances as infinite
vector<int> dist(V, INT_MAX);
// Insert source itself in priority queue and initialize
// its distance as 0.
pq.push({0, src});
dist[src] = 0;
// Looping till priority queue becomes empty (or all
// distances are not finalized)
while (!pq.empty()){
// The first vertex in pair is the minimum distance
// vertex, extract it from priority queue.
int u = pq.top()[1];
pq.pop();
// Get all adjacent of u.
for (auto x : adj[u]){
// Get vertex label and weight of current
// adjacent of u.
int v = x[0];
int weight = x[1];
// If there is shorter path to v through u.
if (dist[v] > dist[u] + weight)
{
// Updating distance of v
dist[v] = dist[u] + weight;
pq.push({dist[v], v});
}
}
}
return dist;
}
//Driver Code Starts{
// Driver program to test methods of graph class
int main(){
int V = 5;
int src = 0;
// edge list format: {u, v, weight}
vector<vector<int>> edges = {{0, 1, 4}, {0, 2, 8}, {1, 4, 6},
{2, 3, 2}, {3, 4, 10}};
vector<int> result = dijkstra(V, edges, src);
// Print shortest distances in one line
for (int dist : result)
cout << dist << " ";
return 0;
}
//Driver Code Ends }
//Driver Code Starts{
import java.util.*;
class GfG {
// Construct adjacency list using ArrayList of ArrayList
static ArrayList<ArrayList<ArrayList<Integer>>>
constructAdj(int[][] edges, int V) {
// Initialize the adjacency list
ArrayList<ArrayList<ArrayList<Integer>>>
adj = new ArrayList<>();
for (int i = 0; i < V; i++) {
adj.add(new ArrayList<>());
}
// Fill the adjacency list from edges
for (int[] edge : edges) {
int u = edge[0];
int v = edge[1];
int wt = edge[2];
// Add edge from u to v
ArrayList<Integer> e1 = new ArrayList<>();
e1.add(v);
e1.add(wt);
adj.get(u).add(e1);
// Since the graph is undirected, add edge from v to u
ArrayList<Integer> e2 = new ArrayList<>();
e2.add(u);
e2.add(wt);
adj.get(v).add(e2);
}
return adj;
}
//Driver Code Ends }
// Returns shortest distances from src to all other vertices
static int[] dijkstra(int V, int[][] edges, int src) {
// Create adjacency list
ArrayList<ArrayList<ArrayList<Integer>>> adj =
constructAdj(edges, V);
// PriorityQueue to store vertices to be processed
// Each element is a pair: [distance, node]
PriorityQueue<ArrayList<Integer>> pq =
new PriorityQueue<>(Comparator.comparingInt(a -> a.get(0)));
// Create a distance array and initialize all distances as infinite
int[] dist = new int[V];
Arrays.fill(dist, Integer.MAX_VALUE);
// Insert source with distance 0
dist[src] = 0;
ArrayList<Integer> start = new ArrayList<>();
start.add(0);
start.add(src);
pq.offer(start);
// Loop until the priority queue is empty
while (!pq.isEmpty()) {
// Get the node with the minimum distance
ArrayList<Integer> curr = pq.poll();
int d = curr.get(0);
int u = curr.get(1);
// Traverse all adjacent vertices of the current node
for (ArrayList<Integer> neighbor : adj.get(u)) {
int v = neighbor.get(0);
int weight = neighbor.get(1);
// If there is a shorter path to v through u
if (dist[v] > dist[u] + weight) {
// Update distance of v
dist[v] = dist[u] + weight;
// Add updated pair to the queue
ArrayList<Integer> temp = new ArrayList<>();
temp.add(dist[v]);
temp.add(v);
pq.offer(temp);
}
}
}
// Return the shortest distance array
return dist;
}
//Driver Code Starts{
// Driver program to test methods of graph class
public static void main(String[] args) {
int V = 5;
int src = 0;
// Edge list format: {u, v, weight}
int[][] edges = {
{0, 1, 4}, {0, 2, 8}, {1, 4, 6},
{2, 3, 2}, {3, 4, 10}
};
// Get shortest path distances
int[] result = dijkstra(V, edges, src);
// Print shortest distances in one line
for (int d : result)
System.out.print(d + " ");
}
}
//Driver Code Ends }
#Driver Code Starts{
import heapq
import sys
# Function to construct adjacency
def constructAdj(edges, V):
# adj[u] = list of [v, wt]
adj = [[] for _ in range(V)]
for edge in edges:
u, v, wt = edge
adj[u].append([v, wt])
adj[v].append([u, wt])
return adj
#Driver Code Ends }
# Returns shortest distances from src to all other vertices
def dijkstra(V, edges, src):
# Create adjacency list
adj = constructAdj(edges, V)
# Create a priority queue to store vertices that
# are being preprocessed.
pq = []
# Create a list for distances and initialize all
# distances as infinite
dist = [sys.maxsize] * V
# Insert source itself in priority queue and initialize
# its distance as 0.
heapq.heappush(pq, [0, src])
dist[src] = 0
# Looping till priority queue becomes empty (or all
# distances are not finalized)
while pq:
# The first vertex in pair is the minimum distance
# vertex, extract it from priority queue.
u = heapq.heappop(pq)[1]
# Get all adjacent of u.
for x in adj[u]:
# Get vertex label and weight of current
# adjacent of u.
v, weight = x[0], x[1]
# If there is shorter path to v through u.
if dist[v] > dist[u] + weight:
# Updating distance of v
dist[v] = dist[u] + weight
heapq.heappush(pq, [dist[v], v])
# Return the shortest distance array
return dist
#Driver Code Starts{
# Driver program to test methods of graph class
if __name__ == "__main__":
V = 5
src = 0
# edge list format: {u, v, weight}
edges =[[0, 1, 4], [0, 2, 8], [1, 4, 6], [2, 3, 2], [3, 4, 10]];
result = dijkstra(V, edges, src)
# Print shortest distances in one line
print(' '.join(map(str, result)))
#Driver Code Ends }
//Driver Code Starts{
using System;
using System.Collections.Generic;
class GfG {
// MinHeap Node (stores vertex and its distance)
class HeapNode {
public int Vertex;
public int Distance;
public HeapNode(int v, int d) {
Vertex = v;
Distance = d;
}
}
// Custom MinHeap class
class MinHeap {
private List<HeapNode> heap = new List<HeapNode>();
public int Count => heap.Count;
private void Swap(int i, int j) {
var temp = heap[i];
heap[i] = heap[j];
heap[j] = temp;
}
public void Push(HeapNode node) {
heap.Add(node);
int i = heap.Count - 1;
while (i > 0) {
int parent = (i - 1) / 2;
if (heap[parent].Distance <= heap[i].Distance)
break;
Swap(i, parent);
i = parent;
}
}
public HeapNode Pop() {
if (heap.Count == 0) return null;
var root = heap[0];
heap[0] = heap[heap.Count - 1];
heap.RemoveAt(heap.Count - 1);
Heapify(0);
return root;
}
private void Heapify(int i) {
int smallest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < heap.Count && heap[left].Distance < heap[smallest].Distance)
smallest = left;
if (right < heap.Count && heap[right].Distance < heap[smallest].Distance)
smallest = right;
if (smallest != i) {
Swap(i, smallest);
Heapify(smallest);
}
}
}
// Build adjacency list from edge list
static List<int[]>[] constructAdj(int[,] edges, int V) {
List<int[]>[] adj = new List<int[]>[V];
for (int i = 0; i < V; i++)
adj[i] = new List<int[]>();
int E = edges.GetLength(0);
for (int i = 0; i < E; i++) {
int u = edges[i, 0];
int v = edges[i, 1];
int wt = edges[i, 2];
adj[u].Add(new int[] { v, wt });
adj[v].Add(new int[] { u, wt }); // Undirected graph
}
return adj;
}
//Driver Code Ends }
// Dijkstra's algorithm using custom MinHeap
static int[] dijkstra(int V, int[,] edges, int src) {
var adj = constructAdj(edges, V);
int[] dist = new int[V];
bool[] visited = new bool[V];
for (int i = 0; i < V; i++)
dist[i] = int.MaxValue;
dist[src] = 0;
MinHeap pq = new MinHeap();
pq.Push(new HeapNode(src, 0));
while (pq.Count > 0) {
HeapNode node = pq.Pop();
int u = node.Vertex;
if (visited[u]) continue;
visited[u] = true;
foreach (var neighbor in adj[u]) {
int v = neighbor[0];
int weight = neighbor[1];
if (!visited[v] && dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight;
pq.Push(new HeapNode(v, dist[v]));
}
}
}
return dist;
}
//Driver Code Starts{
// Main method
static void Main(string[] args) {
int V = 5;
int src = 0;
int[,] edges = {
{0, 1, 4},
{0, 2, 8},
{1, 4, 6},
{2, 3, 2},
{3, 4, 10}
};
int[] result = dijkstra(V, edges, src);
foreach (int d in result)
Console.Write(d + " ");
}
}
//Driver Code Ends }
//Driver Code Starts{
class MinHeap {
constructor() {
this.heap = [];
}
push(val) {
this.heap.push(val);
this._heapifyUp(this.heap.length - 1);
}
pop() {
if (this.size() === 0) return null;
if (this.size() === 1) return this.heap.pop();
const min = this.heap[0];
this.heap[0] = this.heap.pop();
this._heapifyDown(0);
return min;
}
size() {
return this.heap.length;
}
_heapifyUp(index) {
while (index > 0) {
const parent = Math.floor((index - 1) / 2);
if (this.heap[parent][0] <= this.heap[index][0]) break;
[this.heap[parent], this.heap[index]] = [this.heap[index],
this.heap[parent]];
index = parent;
}
}
_heapifyDown(index) {
const n = this.heap.length;
while (true) {
let smallest = index;
const left = 2 * index + 1;
const right = 2 * index + 2;
if (left < n && this.heap[left][0] < this.heap[smallest][0]){
smallest = left;
}
if (right < n && this.heap[right][0] < this.heap[smallest][0]){
smallest = right;
}
if (smallest === index) break;
[this.heap[smallest], this.heap[index]] =
[this.heap[index], this.heap[smallest]];
index = smallest;
}
}
}
// Function to construct adjacency
function constructAdj(edges, V) {
// adj[u] = list of [v, wt]
const adj = Array.from({ length: V }, () => []);
for (const edge of edges) {
const [u, v, wt] = edge;
adj[u].push([v, wt]);
adj[v].push([u, wt]);
}
return adj;
}
//Driver Code Ends }
// Returns shortest distances from src to all other vertices
function dijkstra(V, edges, src) {
// Create adjacency list
const adj = constructAdj(edges, V);
// Create a min heap to store <distance, node>
const minHeap = new MinHeap();
// Create an array for distances and initialize all distances as infinity
const dist = Array(V).fill(Number.MAX_SAFE_INTEGER);
// Push the source node with distance 0
minHeap.push([0, src]);
dist[src] = 0;
// Process the heap
while (minHeap.size() > 0) {
const [d, u] = minHeap.pop();
// Traverse all adjacent of u
for (const [v, weight] of adj[u]) {
if (dist[v] > dist[u] + weight) {
dist[v] = dist[u] + weight;
minHeap.push([dist[v], v]);
}
}
}
return dist;
}
//Driver Code Starts{
// Driver code
const V = 5;
const src = 0;
// edge list format: [u, v, weight]
const edges = [[0, 1, 4], [0, 2, 8], [1, 4, 6], [2, 3, 2], [3, 4, 10]];
const result = dijkstra(V, edges, src);
// Print shortest distances in one line
console.log(result.join(' '));
//Driver Code Ends }
Output
0 4 8 10 10
Time Complexity: O(E*logV), Where E is the number of edges and V is the number of vertices.
Auxiliary Space: O(V), Where V is the number of vertices, We do not count the adjacency list in auxiliary space as it is necessary for representing the input graph.
Problems based on Shortest Path
- Shortest Path in Directed Acyclic Graph
- Shortest path with one curved edge in an undirected Graph
- Minimum Cost Path
- Path with smallest difference between consecutive cells
- Print negative weight cycle in a Directed Graph
- 1st to Kth shortest path lengths in given Graph
- Shortest path in a Binary Maze
- Minimum steps to reach target by a Knight
- Number of ways to reach at destination in shortest time
- Snake and Ladder Problem
- Word Ladder