Open in App
Not now

# Dial’s Algorithm (Optimized Dijkstra for small range weights)

• Difficulty Level : Expert
• Last Updated : 28 Dec, 2022

Dijkstra’s shortest path algorithm runs in O(Elog V) time when implemented with adjacency list representation (See C implementation and STL based C++ implementations for details).

Input : Source = 0, Maximum Weight W = 14
Output :
Vertex       Distance from Source
0                   0
1                   4
2                  12
3                  19
4                  21
5                  11
6                   9
7                   8
8                 14

Consider the below Graph:

The shortest path from source 0

We have learned about how to find the shortest path from a given source vertex to all other vertex using Dijkstra’s shortest path algorithm with the Time Complexity of O(E log V) in this article.

Can we optimize Dijkstra’s shortest path algorithm to work better than O(E log V) if the maximum weight is small (or the range of edge weights is small)? For example, in the above diagram, the maximum weight is 14. Many times the range of weights on edges is in a small range (i.e. all edge weights can be mapped to 0, 1, 2.. w where w is a small number). In that case, Dijkstra’s algorithm can be modified by using different data structures, and buckets, which is called dial implementation of Dijkstra’s algorithm. time complexity is O(E + WV) where W is the maximum weight on any edge of the graph, so we can see that, if W is small then this implementation runs much faster than the traditional algorithm. The following are important observations.

• The maximum distance between any two nodes can be at max w(V – 1) (w is maximum edge weight and we can have at max V-1 edges between two vertices).
• In the Dijkstra algorithm, distances are finalized in non-decreasing, i.e., the distance of the closer (to given source) vertices is finalized before the distant vertices.

Algorithm Below is the complete algorithm:

1. Maintains some buckets, numbered 0, 1, 2,…,wV.
2. Bucket k contains all temporarily labeled nodes with a distance equal to k.
3. Nodes in each bucket are represented by a list of vertices.
4. Buckets 0, 1, 2,..wV are checked sequentially until the first non-empty bucket is found. Each node contained in the first non-empty bucket has the minimum distance label by definition.
5. One by one, these nodes with minimum distance labels are permanently labeled and deleted from the bucket during the scanning process.
6. Thus operations involving vertex include:
• Checking if a bucket is empty
• Adding a vertex to a bucket
• Deleting a vertex from a bucket.
7. The position of a temporarily labeled vertex in the buckets is updated accordingly when the distance label of a vertex changes.
8. The process is repeated until all vertices are permanently labeled (or the distances of all vertices are finalized).

Implementation Since the maximum distance can be w(V – 1), we create wV buckets (more for simplicity of code) for implementation of the algorithm which can be large if w is big.

## C++

 `// C++ Program for Dijkstra's dial implementation` `#include` `using` `namespace` `std;` `# define INF 0x3f3f3f3f`   `// This class represents a directed graph using` `// adjacency list representation` `class` `Graph` `{` `    ``int` `V; ``// No. of vertices` `    ``// In a weighted graph, we need to store vertex` `    ``// and weight pair for every edge` `    ``list< pair<``int``, ``int``> > *adj;`   `public``:` `    ``Graph(``int` `V); ``// Constructor`   `    ``// function to add an edge to graph` `    ``void` `addEdge(``int` `u, ``int` `v, ``int` `w);`   `    ``// prints shortest path from s` `    ``void` `shortestPath(``int` `s, ``int` `W);` `};`   `// Allocates memory for adjacency list` `Graph::Graph(``int` `V)` `{` `    ``this``->V = V;` `    ``adj = ``new` `list< pair<``int``, ``int``> >[V];` `}`   `// adds edge between u and v of weight w` `void` `Graph::addEdge(``int` `u, ``int` `v, ``int` `w)` `{` `    ``adj[u].push_back(make_pair(v, w));` `    ``adj[v].push_back(make_pair(u, w));` `}`   `// Prints shortest paths from src to all other vertices.` `// W is the maximum weight of an edge` `void` `Graph::shortestPath(``int` `src, ``int` `W)` `{` `    ``/* With each distance, iterator to that vertex in` `    ``its bucket is stored so that vertex can be deleted` `    ``in O(1) at time of updation. So` `    ``dist[i].first = distance of ith vertex from src vertex` `    ``dits[i].second = iterator to vertex i in bucket number */` `    ``vector::iterator> > dist(V);`   `    ``// Initialize all distances as infinite (INF)` `    ``for` `(``int` `i = 0; i < V; i++)` `        ``dist[i].first = INF;`   `    ``// Create buckets B[].` `    ``// B[i] keep vertex of distance label i` `    ``list<``int``> B[W * V + 1];`   `    ``B[0].push_back(src);` `    ``dist[src].first = 0;`   `    ``//` `    ``int` `idx = 0;` `    ``while` `(1)` `    ``{` `        ``// Go sequentially through buckets till one non-empty` `        ``// bucket is found` `        ``while` `(B[idx].size() == 0 && idx < W*V)` `            ``idx++;`   `        ``// If all buckets are empty, we are done.` `        ``if` `(idx == W * V)` `            ``break``;`   `        ``// Take top vertex from bucket and pop it` `        ``int` `u = B[idx].front();` `        ``B[idx].pop_front();`   `        ``// Process all adjacents of extracted vertex 'u' and` `        ``// update their distanced if required.` `        ``for` `(``auto` `i = adj[u].begin(); i != adj[u].end(); ++i)` `        ``{` `            ``int` `v = (*i).first;` `            ``int` `weight = (*i).second;`   `            ``int` `du = dist[u].first;` `            ``int` `dv = dist[v].first;`   `            ``// If there is shorted path to v through u.` `            ``if` `(dv > du + weight)` `            ``{` `                ``// If dv is not INF then it must be in B[dv]` `                ``// bucket, so erase its entry using iterator` `                ``// in O(1)` `                ``if` `(dv != INF)` `                    ``B[dv].erase(dist[v].second);`   `                ``// updating the distance` `                ``dist[v].first = du + weight;` `                ``dv = dist[v].first;`   `                ``// pushing vertex v into updated distance's bucket` `                ``B[dv].push_front(v);`   `                ``// storing updated iterator in dist[v].second` `                ``dist[v].second = B[dv].begin();` `            ``}` `        ``}` `    ``}`   `    ``// Print shortest distances stored in dist[]` `    ``printf``(``"Vertex Distance from Source\n"``);` `    ``for` `(``int` `i = 0; i < V; ++i)` `        ``printf``(``"%d     %d\n"``, i, dist[i].first);` `}`   `// Driver program to test methods of graph class` `int` `main()` `{` `    ``// create the graph given in above figure` `    ``int` `V = 9;` `    ``Graph g(V);`   `    ``// making above shown graph` `    ``g.addEdge(0, 1, 4);` `    ``g.addEdge(0, 7, 8);` `    ``g.addEdge(1, 2, 8);` `    ``g.addEdge(1, 7, 11);` `    ``g.addEdge(2, 3, 7);` `    ``g.addEdge(2, 8, 2);` `    ``g.addEdge(2, 5, 4);` `    ``g.addEdge(3, 4, 9);` `    ``g.addEdge(3, 5, 14);` `    ``g.addEdge(4, 5, 10);` `    ``g.addEdge(5, 6, 2);` `    ``g.addEdge(6, 7, 1);` `    ``g.addEdge(6, 8, 6);` `    ``g.addEdge(7, 8, 7);`   `    ``// maximum weighted edge - 14` `    ``g.shortestPath(0, 14);`   `    ``return` `0;` `}`   `// This code is contributed by Aditya Kumar (adityakumar129)`

## Python3

 `from` `typing ``import` `List``, ``Tuple` `INF ``=` `0x3f3f3f3f`   `# This class represents a directed graph using adjacency list representation` `class` `Graph:` `    ``def` `__init__(``self``, V: ``int``):` `        ``# No. of vertices` `        ``self``.V ``=` `V` `        `  `        ``# In a weighted graph, we need to store vertex and weight pair for every edge` `        ``self``.adj ``=` `[[] ``for` `_ ``in` `range``(V)]`   `    ``# function to add an edge to graph` `    ``def` `addEdge(``self``, u: ``int``, v: ``int``, w: ``int``):` `        ``self``.adj[u].append((v, w))` `        ``self``.adj[v].append((u, w))`   `    ``# Prints shortest paths from src to all other vertices.` `    ``# W is the maximum weight of an edge` `    ``def` `shortestPath(``self``, src: ``int``, W: ``int``):` `        ``# With each distance, iterator to that vertex in its bucket is stored so that vertex can be deleted` `        ``# in O(1) at time of updation. So dist[i][0] = distance of ith vertex from src vertex` `        ``# dist[i][1] = iterator to vertex i in bucket number` `        ``dist ``=` `[[INF, ``None``] ``for` `_ ``in` `range``(``self``.V)]`   `        ``# Initialize distance of source vertex` `        ``dist[src][``0``] ``=` `0`   `        ``# Create buckets B[].` `        ``# B[i] keep vertex of distance label i` `        ``B ``=` `[[] ``for` `_ ``in` `range``(W ``*` `self``.V ``+` `1``)]` `        ``B[``0``].append(src)`   `        ``idx ``=` `0` `        ``while` `True``:` `            ``# Go sequentially through buckets till one non-empty bucket is found` `            ``while` `len``(B[idx]) ``=``=` `0` `and` `idx < W ``*` `self``.V:` `                ``idx ``+``=` `1`   `            ``# If all buckets are empty, we are done.` `            ``if` `idx ``=``=` `W ``*` `self``.V:` `                ``break`   `            ``# Take top vertex from bucket and pop it` `            ``u ``=` `B[idx][``0``]` `            ``B[idx].pop(``0``)`   `            ``# Process all adjacents of extracted vertex ` `            ``# 'u' and update their distances if required.` `            ``for` `v, weight ``in` `self``.adj[u]:` `                ``du ``=` `dist[u][``0``]` `                ``dv ``=` `dist[v][``0``]`   `                ``# If there is shorted path to v through u.` `                ``if` `dv > du ``+` `weight:` `                    ``# If dv is not INF then it must be in ` `                    ``# B[dv] bucket, so erase its entry using iterator` `                    ``# in O(1)` `                    ``if` `dv !``=` `INF:` `                        ``B[dv].remove(v)`   `                    ``# updating the distance` `                    ``dist[v][``0``] ``=` `du ``+` `weight` `                    ``dv ``=` `dist[v][``0``]`   `                    ``# pushing vertex v into updated distance's bucket` `                    ``B[dv].append(v)`   `                    ``# storing updated iterator in dist[v][1]` `                    ``dist[v][``1``] ``=` `len``(B[dv]) ``-` `1`   `        ``# Print shortest distances stored in dist[]` `        ``print``(``"Vertex Distance from Source"``)` `        ``for` `i ``in` `range``(``self``.V):` `            ``print``(f``"{i}     {dist[i][0]}"``)`   `# Driver program to test methods of graph class` `def` `main():` `    ``# create the graph given in above figure` `    ``V ``=` `9` `    ``W ``=` `14` `    ``g ``=` `Graph(V)`   `    ``g.addEdge(``0``, ``1``, ``4``)` `    ``g.addEdge(``0``, ``7``, ``8``)` `    ``g.addEdge(``1``, ``2``, ``8``)` `    ``g.addEdge(``1``, ``7``, ``11``)` `    ``g.addEdge(``2``, ``3``, ``7``)` `    ``g.addEdge(``2``, ``8``, ``2``)` `    ``g.addEdge(``2``, ``5``, ``4``)` `    ``g.addEdge(``3``, ``4``, ``9``)` `    ``g.addEdge(``3``, ``5``, ``14``)` `    ``g.addEdge(``4``, ``5``, ``10``)` `    ``g.addEdge(``5``, ``6``, ``2``)` `    ``g.addEdge(``6``, ``7``, ``1``)` `    ``g.addEdge(``6``, ``8``, ``6``)` `    ``g.addEdge(``7``, ``8``, ``7``)`   `    ``g.shortestPath(``0``, W)`   `if` `__name__ ``=``=` `"__main__"``:` `    ``main()` `    `  `# This code is contributed by sanjanasikarwar24`

## C#

 `// C# Program for Dijkstra's dial implementation` `using` `System;` `using` `System.Collections.Generic;`   `// This class represents a directed graph using` `// adjacency list representation` `public` `class` `Graph ` `{` `  ``static` `readonly` `int` `INF = Int32.MaxValue;` `  ``private` `int` `V; ``// No. of vertices` `  ``// In a weighted graph, we need to store vertex` `  ``// and weight pair for every edge` `  ``private` `List >[] adj;`   `  ``public` `Graph(``int` `v) ``// Constructor` `  ``{` `    ``this``.V = v;` `    ``this``.adj = ``new` `List >[ v ];` `    ``for` `(``int` `i = 0; i < v; i++)` `      ``this``.adj[i] = ``new` `List >();` `  ``}`   `  ``// function to Add an edge to graph` `  ``// Adds edge between u and v of weight w` `  ``public` `void` `AddEdge(``int` `u, ``int` `v, ``int` `w)` `  ``{` `    ``adj[u].Add(Tuple.Create(v, w));` `    ``adj[v].Add(Tuple.Create(u, w));` `  ``}`   `  ``// Prints shortest paths from src to all other vertices.` `  ``// W is the maximum weight of an edge` `  ``public` `void` `shortestPath(``int` `src, ``int` `W)` `  ``{` `    ``/* With each distance, iterator to that vertex in` `        ``its bucket is stored so that vertex can be deleted` `        ``in O(1) at time of updation. So` `        ``dist[i].first = distance of ith vertex from src` `        ``vertex dits[i].second = iterator to vertex i in` `        ``bucket number */` `    ``int``[] dist = ``new` `int``[V];`   `    ``// Initialize all distances as infinite (INF)` `    ``for` `(``int` `i = 0; i < V; i++)` `      ``dist[i] = INF;`   `    ``// Create buckets B[].` `    ``// B[i] keep vertex of distance label i` `    ``List<``int``>[] B = ``new` `List<``int``>[ W * V + 1 ];` `    ``for` `(``int` `i = 0; i < W * V + 1; i++)` `      ``B[i] = ``new` `List<``int``>();`   `    ``B[0].Add(src);` `    ``dist[src] = 0;`   `    ``int` `idx = 0;` `    ``while` `(``true``) {` `      ``// Go sequentially through buckets till one` `      ``// non-empty bucket is found` `      ``while` `(B[idx].Count == 0 && idx < W * V)` `        ``idx++;`   `      ``// If all buckets are empty, we are done.` `      ``if` `(idx == W * V)` `        ``break``;`   `      ``// Take top vertex from bucket and pop it` `      ``int` `u = B[idx][0];` `      ``B[idx].Remove(u);`   `      ``// Process all adjacents of extracted vertex 'u'` `      ``// and update their distances if required.` `      ``foreach``(Tuple<``int``, ``int``> i ``in` `adj[u])` `      ``{` `        ``int` `v = i.Item1;` `        ``int` `weight = i.Item2;`   `        ``int` `du = dist[u];` `        ``int` `dv = dist[v];`   `        ``// If there is shorted path to v through u.` `        ``if` `(dv > du + weight) {` `          ``// updating the distance` `          ``dist[v] = du + weight;` `          ``dv = dist[v];`   `          ``// pushing vertex v into updated` `          ``// distance's bucket` `          ``B[dv].Insert(0, v);` `        ``}` `      ``}` `    ``}`   `    ``// Print shortest distances stored in dist[]` `    ``Console.WriteLine(``"Vertex Distance from Source"``);` `    ``for` `(``int` `i = 0; i < V; ++i)` `      ``Console.WriteLine(``"{0}     {1}"``, i, dist[i]);` `  ``}` `}`   `class` `GFG {` `  ``// Driver program to test methods of graph class` `  ``static` `void` `Main(``string``[] args)` `  ``{` `    ``// create the graph given in above figure` `    ``int` `V = 9;` `    ``Graph g = ``new` `Graph(V);`   `    ``// making above shown graph` `    ``g.AddEdge(0, 1, 4);` `    ``g.AddEdge(0, 7, 8);` `    ``g.AddEdge(1, 2, 8);` `    ``g.AddEdge(1, 7, 11);` `    ``g.AddEdge(2, 3, 7);` `    ``g.AddEdge(2, 8, 2);` `    ``g.AddEdge(2, 5, 4);` `    ``g.AddEdge(3, 4, 9);` `    ``g.AddEdge(3, 5, 14);` `    ``g.AddEdge(4, 5, 10);` `    ``g.AddEdge(5, 6, 2);` `    ``g.AddEdge(6, 7, 1);` `    ``g.AddEdge(6, 8, 6);` `    ``g.AddEdge(7, 8, 7);`   `    ``// maximum weighted edge - 14` `    ``g.shortestPath(0, 14);` `  ``}` `}`   `// This code is contributed by cavi4762`

Output:

```Vertex Distance from Source
0     0
1     4
2     12
3     19
4     21
5     11
6     9
7     8
8     14```

Illustration: Below is the step-by-step illustration taken from here.