Purpose: Shortest paths when all edge weights are small non-negative integers , in — replacing Dijkstra’s priority queue with an array of buckets.
The Idea
Dijkstra spends per operation maintaining a heap ordered by distance. If distances are bounded by , you can instead keep an array bucket[0..D] where bucket[d] holds the vertices at tentative distance , and sweep upward. Each bucket access is .
vector<int> dial(int n, int s, vector<vector<pair<int,int>>>& adj, int C) {
int D = (n - 1) * C;
vector<int> dist(n, INT_MAX);
vector<vector<int>> bucket(D + 1);
dist[s] = 0;
bucket[0].push_back(s);
for (int d = 0; d <= D; d++) {
while (!bucket[d].empty()) {
int u = bucket[d].back(); bucket[d].pop_back();
if (dist[u] != d) continue; // stale entry
for (auto [v, w] : adj[u])
if (d + w < dist[v]) {
dist[v] = d + w;
bucket[d + w].push_back(v);
}
}
}
return dist;
}Circular buckets — the memory fix
The full array is , which can be huge. But at any moment the live distances span only , so buckets suffice if you index them modulo :
vector<vector<int>> bucket(C + 1);
// insert v at distance nd: bucket[nd % (C + 1)].push_back(v);This brings the space down to and is the version worth writing.
Complexity comparison
| Weights | Algorithm | Time |
|---|---|---|
| all 1 | BFS | |
| 0-1 BFS | ||
| integers, small | Dial | or with circular buckets |
| arbitrary non-negative | Dijkstra | |
| arbitrary, Fibonacci heap | Dijkstra | |
| integers, word RAM | Thorup | — theoretical |
Dial wins when roughly; beyond that the bucket sweep costs more than the heap.
Where it appears
- Small integer costs — grids where each move costs 1-5, edge colours with small penalties
- Radix heaps — the generalisation: buckets by the highest differing bit, giving Dijkstra
- Timetable and routing problems with discretised times
- 0-1 BFS — the special case, where two buckets (a deque) suffice
Practical note
In a contest, Dijkstra with
priority_queuehandles in well under a second, so Dial is rarely necessary. Its value is knowing that “the priority queue is the only slow part” and that bounded weights let you delete it. The same insight produces the deque in 0-1 BFS, which is commonly needed.
See also: 0-1 BFS · Dijkstra · Shortest Paths