dsa2 min read

Shortest Path Algorithms from Scratch (2026)

Shortest Path Algorithms from Scratch (2026)

Published:  |  Category: Dsa  |  Reading time: ~15 min
Shortest Path Algorithms from Scratch (2026)

Shortest path algorithms are fundamental to graph theory, determining the minimal distance between nodes in a weighted graph. Dijkstra, Bellman-Ford, and Floyd-Warshall each serve distinct use cases with different trade-offs.

Dijkstra's algorithm handles non-negative weights efficiently using a priority queue, Bellman-Ford detects negative cycles through iterative relaxation, and Floyd-Warshall computes all-pairs shortest paths via dynamic programming.

Dijkstra's Algorithm

Dijkstra's algorithm finds the shortest path from a source to all vertices using a greedy approach. It maintains a priority queue of vertices ordered by their current distance and relaxes edges from the closest unprocessed vertex.

The algorithm runs in O((V+E) log V) with a binary heap and fails on negative weight edges because it assumes earlier settled distances are final.

vector dijkstra(vector>>& graph, int src) {
    int V = graph.size();
    vector dist(V, INT_MAX);
    dist[src] = 0;
    priority_queue, vector>, greater<>> pq;
    pq.push({0, src});
    while (!pq.empty()) {
        auto [d, u] = pq.top(); pq.pop();
        if (d > dist[u]) continue;
        for (auto [v, w] : graph[u])
            if (dist[u] + w < dist[v])
                dist[v] = dist[u] + w, pq.push({dist[v], v});
    }
    return dist;
}

Bellman-Ford Algorithm

Bellman-Ford iteratively relaxes all edges V-1 times to guarantee shortest paths. A final pass detects negative cycles reachable from the source.

Its O(VE) complexity makes it slower than Dijkstra, but it handles negative weights and cycle detection, making it essential for general-purpose shortest path problems.

vector bellmanFord(int V, vector>& edges, int src) {
    vector dist(V, INT_MAX);
    dist[src] = 0;
    for (int i = 0; i < V - 1; i++)
        for (auto& e : edges)
            if (dist[e[0]] != INT_MAX && dist[e[0]] + e[2] < dist[e[1]])
                dist[e[1]] = dist[e[0]] + e[2];
    for (auto& e : edges)
        if (dist[e[0]] != INT_MAX && dist[e[0]] + e[2] < dist[e[1]])
            return {}; // negative cycle
    return dist;
}

Floyd-Warshall Algorithm

Floyd-Warshall computes shortest paths between all pairs using a 2D DP matrix. For each intermediate vertex k, it checks whether path i->k->j is shorter than i->j.

With O(V³) time, it is ideal for dense graphs or when all-pairs distances are needed, and it can detect negative cycles by checking diagonal entries.

vector> floydWarshall(vector>& graph) {
    int V = graph.size();
    vector> dist = graph;
    for (int k = 0; k < V; k++)
        for (int i = 0; i < V; i++)
            for (int j = 0; j < V; j++)
                if (dist[i][k] != INT_MAX && dist[k][j] != INT_MAX)
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    return dist;
}

Frequently Asked Questions

When should I use Dijkstra over Bellman-Ford?

Use Dijkstra when all edge weights are non-negative and you need better O((V+E) log V) performance. Use Bellman-Ford when negative weights exist or you need to detect negative cycles.

Can Floyd-Warshall handle negative weights?

Yes, Floyd-Warshall handles negative weights and detects negative cycles, but it does not work with negative cycles in the shortest path computation as distances become -infinity.

Originally published on Ayodhyyya. Last updated June 1, 2026.