12. What is the Bellman-Ford algorithm for finding single source shortest paths? What are its main advantages over Dijkstra? Use C . Algorithm, Question, Explanation, Solution. At toptal-com .
By: Chrysanthus Date Published: 3 Feb 2026
A negative cycle is a path that can be followed in cycles, where the sum of the edge weights is negative. Using the basic Bellman-Ford algorithm on a graph with negative cycles will not produce a result of shortest paths because in a negative cycle, one can always go one more cycle and get a shorter path. Luckily, the basic Bellman-Ford algorithm can be modified to safely detect and report the presence of negative cycles; but that will not be addressed in this article
An edge weight is the value of the edge.
This is a teaching document, so for an actual interview, summarize all what is given in this document.
Explanation of the Basic Bellman-Ford Algorithm
In this section, Bellman-Ford Algorithm is illustrated first, before the algorithm is given as a series of steps. After that, the code is given based on the illustration (manual-run-through).
Manual-Run-Through of Bellman-Ford Algorithm

V is the number of vertices and E is the number of edges. Do not confuse between edge and edge-weight.
For this problem, the source is D, and the shortest distance from D to each of the other vertices has to be determined, bearing in mind that some edges have negative values in their forward directions.
The first thing to do is to set the distance from D to D itself, as 0; then set the distance to each of the other vertices from D, as positive infinity, as it assumes the algorithm is not yet aware of their presence. Infinity is an unimaginably large number. The following image shows this:

The table corresponding to this initial state is:
| Previous Vertex | Vertex | Cost |
|---|---|---|
| A | infinity | |
| B | infinity | |
| C | infinity | |
| D | 0 | |
| E | infinity |
At the beginning, list all the vertices in the middle column in ascending order.
Rounds
Bellman-Ford Algorithm is done in rounds. When there are V vertices, the number of rounds is V - 1. There are 5 vertices here, and so the number of rounds is 4 = 5 - 1.
In each round, all the edges have to be checked, one time. The different edges from the diagram are:
(D-A), (D-C), (D-E), (A-E), (A-C), (E-B), (E-C), (B-C), (C-A);
all 9 edges. The order in which the edges are arranged from left to right, in this line, does not matter. Note that the first letter is the start of a particular edge and the last (second) letter is the end of that same edge, in the forward direction of the arrow-head; though some edge weights might have negative values. In the table, the particular edge start letter is in the first column, while the end (second) letter is in the second (middle) column, row by row. So, for a particular edge, the left (first) letter is the previous vertex and the right (end) letter is the vertex in question. The cost of the end (second or right) vertex is in the third column in the same row. As the algorithm proceeds in a round, the start or previous letter in a row, in the first column may change, indicating a neighboring edge to the same end vertex (letter).
In any round, all the vertices (9) are assessed to know the assumed cost for each vertex. The cost of each vertex is the assumed distance from the source, D. Always bear in mind that it is the minimum distance from D that is looked for. And so, when a new cost is found to be lower than a former cost, the new cost replaces the former cost for that vertex. That is called relaxation.
At the beginning of the algorithm, the cost of D is 0 and the cost of the other vertices are each infinity.
Round 1
The list of edges is:
(D-A), (D-C), (D-E), (A-E), (A-C), (E-B), (E-C), (B-C), (C-A)
copied from above.
With the edge (D-A), the cost of A should become 4 = 0+4 and 4 is less than infinity. So 4 has to replace infinity in the circle of A in the diagram. In the A (middle column) row in the table, the value in the third column has to become 4 and the value in the first column has to be D, the previous (or start) letter of the current edge.
With the edge (D-C), the cost of C should become 7 = 0+7 and 7 is less than infinity. So 7 has to replace infinity in the circle of C in the diagram. In the C (middle column) row in the table, the value in the third column has to become 7 and the value in the first column has to become D, the previous (or start) letter of the current edge.
The reader should be filling the values in the table in his/her rough work, as the round continues.

With the edge (E-B), the cost of B should become 5 = 3+2 (the 3 here is the current cost of E in the circle of E) and 5 is less than infinity, the assumed shortest cost of B. So 5 replaces infinity in the circle of B in the diagram. In the B (middle column) row in the table, the value in the third column becomes 5 and the value in the first column becomes E, the previous (or start) letter of the current edge. At this point, still in the first round, there is no longer any infinity value in the third column of the table.



The Bellman-Ford algorithm now has checked each edge 1 time. Round one ends ! The final state of the table in round 1 is:
| Previous Vertex | Vertex | Cost |
|---|---|---|
| C | A | -2 |
| E | B | 5 |
| B | C | 1 |
| D | 0 | |
| D | E | 3 |
Note that there is no letter in the first column cell of row D, as the distance from D to D is 0. The cost of D is 0.
Round 2
There has to be 4 rounds for 5-1 = 4 of V-1. In each round, all the edges have to be checked again for shortest path from D. Each edge is checked or assessed once. The edges are:
(D-A), (D-C), (D-E), (A-E), (A-C), (E-B), (E-C), (B-C), (C-A);
copied from above.
With the edge (D-A), the cost of A should become 4 = 0+4, but 4 is not less than -2. So 4 does not replace -2 in the circle of A in the diagram. In the A (middle column) row in the table, the value in the third column remains at -2 and the value in the first column remains at C, the previous (or start) letter of a neighboring edge.
With the edge (D-C), the cost of C should become 7 = 0+7, but 7 is not less than 1. So 7 does not replace 1 in the circle of C in the diagram. In the C (middle column) row in the table, the value in the third column remains at 1 and the value in the first column remains at B, the previous (or start) letter of a neighboring edge.
The final table for round 1 has not yet changed.
With the edge (D-E), the cost of E should become 3 = 0+3, but 3 is not less than the 3 which is still at E. So 3 does not replace the 3 which is still in the circle of E in the diagram. In the E (middle column) row in the table, the value in the third column remains at 3 and the value in the first column remains at D, the previous (or start) letter of the current or neighboring edge. Note that the table at its last state in round 1 has still not changed and the state of the final diagram in round 1 has still not changed. The current diagram in this second round is still what the algorithm had at the end of round 1. It is still:

With the edge (A-C), the cost of C at this point in the second round, should become 2 = -2+4 (the -2 here is the current cost of A in the circle of A). 2 is not less than 1, the assumed shortest cost of C, from the first round. So 2 does not replace 1 in the circle of C in the diagram. In the C (middle column) row in the table, the value in the third column remains at the last value of 1 from the first round, and the value in the first column remains at the last value of B, the previous (or start) letter of a neighboring edge, from the first round.
With the edge (E-B), the cost of B should become 5 = 3+2 (the 3 here is the current cost of E in the circle of E). The 5 here is the same 5 in the first round, the assumed shortest cost of B. This same 5 is not less than itself. So it does not replace itself in the circle of B in the diagram. Do not forget that the idea is to look for the shortest path within a round and in the next round. In the B (middle column) row in the table, the value in the third column remains at 5 and the value in the first column remains at E, the previous (or start) letter of the current edge.
With the edge (E-C), the cost of C should become 6 = 3+3 (the first 3 here is the current cost of E in the circle of E), but 6 is not less than 1, the assumed shortest cost of C, at this point. So 6 does not replace 1 in the circle of C in the diagram - in this second round. In the C (middle column) row in the table, the value in the third column remains at 1 and the value in the first column remains at B, the previous (or start) letter of a neighboring edge (is B). The following diagram shows the current state (no change), in still the second round:



| Previous Vertex | Vertex | Cost |
|---|---|---|
| C | A | -2 |
| E | B | 5 |
| B | C | 1 |
| D | 0 | |
| D | E | 3 |
It is important to note here, that though there were some changes in the calculations in the second round, the final result (of the diagram and table) has not changed from that of the first round.
Now, with other similar graph networks, up to 4 rounds, 5-1 (V-1) have to be done to have the final and stable state. However here, only two rounds had to be made to have the final and stable state.
With the Bellman-Ford algorithm, once the new round has no difference in final diagram and final table, with the final diagram and final table of the preceding round, then the algorithm should stop and not waste any more time checking more rounds and edges. It should stop because the diagram and table have become stable, and further rounds will not bring in any new change.
If the number of rounds go beyond V-1, then there is at least one negative cycle in the graph. However that is not addressed in this document.
So the final state of the Bellman-Ford algorithm for the above problem has been attained. The next issue is to obtain the shortest path from D, to reach each of the other vertices from the final state (the table). The shortest path should be obtained both in path-weight and order of vertices.
Obtaining the Shortest Path of the Other Vertices
The shortest path from D to D is 0, from definition.Shortest Path Weight of other Vertices
To obtain the shortest path weight of the other vertices, use the final state of the table at the last round (for the above problem, second round). Each value in the third column is the shortest path-weight from D, and not from the corresponding table row value in the first column.Locate the vertex (letter) in the middle column of the table. The value in the third column of the same row is its shortest path-weight from D. This can also be read from the circle of the vertex from the final diagram of the last round (for the above problem, second round).
The diagram can also be used instead of the table, if the costs of the different vertices were updated as the edges were assessed (checked).
The shortest path weight of A is -2 and not 4. This is a graph with directed edges, some of whose values are negative. The shortest path weight of C is 1 and not 7.
The shortest path weight of B is 5. That coincidentally can be seen from the given diagram. The shortest path weight of E is 3. That coincidentally can also be seen from the given diagram.
Shortest Path by Order of Vertices

| Previous Vertex | Vertex | Cost |
|---|---|---|
| C | A | -2 |
| E | B | 5 |
| B | C | 1 |
| D | 0 | |
| D | E | 3 |
For the shortest path of B , locate B in the middle column, second row in the table. The previous vertex that connects to B for the single corresponding edge for B, going backwards ultimately to D, is E, in the first column in the same (second) row. The weight of this edge is 2 (from the given diagram).
This previous vertex E, has to be located as the end vertex of an edge in the middle column. It is located in the middle column in row 5. The previous vertex for the single edge of interest that ends at E is D, in the same row (row 5). The weight of this edge is 3 (from the given diagram). D has been arrived at. Writing the path in forward order of vertices from the table (without repeating a vertex), gives:
D-E-B
Adding the path weights in forward order is:
3+2 = 5 (for D-E and E-B)
For the shortest path of A, locate A in the middle column, first row in the table. The previous vertex that connects to A for the single corresponding edge from A, going backwards ultimately to D, is C (not D), in the first column in the same (first) row. The weight of this edge is -3 (from the given diagram).
This previous vertex C, has to be located as the end vertex of an edge in the middle column. It is located in the middle column in row 3. The previous vertex for the single edge of interest that ends at C is B, in the same row (row 3). The weight of this edge is -4.
This previous vertex B, has to be located as the end vertex of an edge in the middle column. It is located in the middle column in row 2. The previous vertex that connects to B for the single corresponding edge for B, going backwards ultimately to D, is E, in the first column in the same (second) row. The weight of this edge is 2 (from the given diagram).
This previous vertex E, has to be located as the end vertex of an edge in the middle column. It is located in the middle column in row 5. The previous vertex for the single edge of interest that ends at E is D, in the same row (row 5). The weight of this edge is 3. D has been arrived at, in the first column. Writing the path in forward order of vertices from the table (without repeating a vertex), gives:
D-E-B-C-A
Adding the path weights in forward order is:
3+2+-4+-3 = 3+2-4-3= -2 (for D-E, E-B, B-C and C-A)
The path order and sum path weight of the remaining two vertices are determined in the same way.
Bellman-Ford Algorithm as a Series of Steps
- The cost from the source vertex to itself is 0.- The cost from the source vertex to each of the other vertices is infinity, at the start of the algorithm.
- Produce a table with 3 columns, where the first column is for the previous vertex of an edge of interest, the middle column is for the end vertex for the same edge of interest, and the third and last column is for the temporary cost of the end vertex from D, temporarily ending with the edge of interest.
- Each edge in the whole graph has to be assessed in rounds.
- The maximum number of rounds is V-1 where V is the number of vertices.
- When each vertex is assessed in a round, the corresponding row cell in the third column of the table is updated appropriately with the cost.
- Once the new round has no difference in final diagram and final table, with the final diagram and final table of the preceding round, then the algorithm should stop, and not waste any more time checking more rounds and edges.
- If the number of rounds go beyond V-1, then there is at least one negative cycle in the graph.
Basic Code for Bellman-Ford Algorithm
The Adjacency Matrix table for the above graph is:A B C D E
A 4 5
B -4
C -3
D 4 7 3
E 2 3
Excluding the include directives, there are six main code segments for the program. This does not include the main() function, where the given matrix is formed and the bellmanFord() function is called.
The Graph Class Code Segment
The first code segment produces a class for the graph.
The createGraph() Code Segment
This code segment (function) instantiates a graph object from the Graph class and returns the instance.
The addEdge() code segment
An edge here is the weight or distance from one vertex to a neighboring vertex. In the adjacency matrix, this is the value of the intersection cell of the row (index) of one of the vertices and the column (index) of the other vertex. This function (code segment) achieves that.
The addVertexData() Code Segment
This function (code segment) assigns to an index of interest, the corresponding letter (of the alphabet).
The bellmanFord() Code Segment
This function (code segment) is the core of the program. It performs the Bellman-Ford algorithm.
The freeGraph() Code Segment
This code segment (function) frees dynamic memory.
Complete Program for Basic Bellman-Ford Algorithm
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#define MAX_VERTEX_DATA 10 // Maximum length of vertex data string
typedef struct {
int size;
int **adjMatrix;
char **vertexData;
} Graph;
Graph* createGraph(int size) {
Graph *g = (Graph*)malloc(sizeof(Graph));
g->size = size;
// Allocate memory for adjacency matrix
g->adjMatrix = (int**)malloc(size * sizeof(int*));
for (int i = 0; i < size; i++) {
g->adjMatrix[i] = (int*)calloc(size, sizeof(int));
}
// Allocate memory for vertex data
g->vertexData = (char**)malloc(size * sizeof(char*));
for (int i = 0; i < size; i++) {
g->vertexData[i] = (char*)calloc(MAX_VERTEX_DATA, sizeof(char));
}
return g;
}
void addEdge(Graph *g, int u, int v, int weight) {
if (u >= 0 && u < g->size && v >= 0 && v < g->size) {
g->adjMatrix[u][v] = weight;
//g->adjMatrix[v][u] = weight; // For undirected graph
}
}
void addVertexData(Graph *g, int vertex, const char *data) {
if (vertex >= 0 && vertex < g->size) {
strncpy(g->vertexData[vertex], data, MAX_VERTEX_DATA - 1);
}
}
void bellmanFord(Graph *g, const char *startVertexData) {
int startVertex = -1;
for (int i = 0; i < g->size; i++) {
if (strcmp(g->vertexData[i], startVertexData) == 0) {
startVertex = i;
break;
}
}
if (startVertex == -1) {
printf("Start vertex not found\n");
return;
}
int distances[g->size];
for (int i = 0; i < g->size; i++) {
distances[i] = INT_MAX;
}
distances[startVertex] = 0;
for (int i = 0; i < g->size - 1; i++) {
for (int u = 0; u < g->size; u++) {
for (int v = 0; v < g->size; v++) {
if (g->adjMatrix[u][v] != 0 && distances[u] != INT_MAX &&
distances[u] + g->adjMatrix[u][v] < distances[v]) {
distances[v] = distances[u] + g->adjMatrix[u][v];
printf("Relaxing edge %s->%s, Updated distance to %s: %d\n",g->vertexData[u], g->vertexData[v], g->vertexData[v], distances[v]);
}
}
}
}
// Print distances
for (int i = 0; i < g->size; i++) {
printf("Distance from %s to %s: %d\n", startVertexData, g->vertexData[i], distances[i]);
}
}
void freeGraph(Graph *g) {
if (g != NULL) {
// Free each row of the adjacency matrix
for (int i = 0; i < g->size; i++) {
free(g->adjMatrix[i]);
}
// Free the adjacency matrix itself
free(g->adjMatrix);
// Free each vertex data string
for (int i = 0; i < g->size; i++) {
free(g->vertexData[i]);
}
// Free the vertex data array
free(g->vertexData);
// Finally, free the graph structure
free(g);
}
}
int main() {
Graph *g = createGraph(5);
addVertexData(g, 0, "A");
addVertexData(g, 1, "B");
addVertexData(g, 2, "C");
addVertexData(g, 3, "D");
addVertexData(g, 4, "E");
addEdge(g, 3, 0, 4); // D -> A, weight 4
addEdge(g, 3, 2, 7); // D -> C, weight 7
addEdge(g, 3, 4, 3); // D -> E, weight 3
addEdge(g, 0, 2, 4); // A -> C, weight 4
addEdge(g, 2, 0, -3); // C -> A, weight -3
addEdge(g, 0, 4, 5); // A -> E, weight 5
addEdge(g, 4, 2, 3); // E -> C, weight 3
addEdge(g, 1, 2, -4); // B -> C, weight -4
addEdge(g, 4, 1, 2); // E -> B, weight 2
printf("\nThe Bellman-Ford Algorithm starting from vertex D:\n");
bellmanFord(g, "D");
freeGraph(g); //Freeing up memory
return 0;
}
The Bellman-Ford Algorithm starting from vertex D:
Relaxing edge D->A, Updated distance to A: 4
Relaxing edge D->C, Updated distance to C: 7
Relaxing edge D->E, Updated distance to E: 3
Relaxing edge E->B, Updated distance to B: 5
Relaxing edge E->C, Updated distance to C: 6
Relaxing edge B->C, Updated distance to C: 1
Relaxing edge C->A, Updated distance to A: -2
Distance from D to A: -2
Distance from D to B: 5
Distance from D to C: 1
Distance from D to D: 0
Distance from D to E: 3
Adjacency Matrix Graph Representation has been used in the code.
Time Complexity for Basic Bellman-Ford Algorithm
The worst-case time complexity for Bellman-Ford Algorithm is:O(V3)
where V is the number of vertices.
Advantages of Bellman-Ford over Dijkstra
There are just two advantages:- Bellman-Ford algorithm can find the shortest paths in graphs with negative edges, which Dijkstra's algorithm cannot do.
- Though this second advantage has not been addressed in this document, the complete Bellman-Ford algorithm can detect negative cycles in a graph, which Dijkstra's algorithm cannot do.
For disadvantage (not asked), it is generally slower than Dijkstra's algorithm