Step 5 of 6
83% CompleteShortest Path Algorithms
Learn algorithms for finding shortest paths in weighted graphs
Shortest Path Algorithms
Finding the shortest path between vertices is a fundamental problem in graph theory with applications in navigation, networking, and optimization. Different algorithms excel in different scenarios based on edge weights and graph properties.
1. Dijkstra's Algorithm
Dijkstra's algorithm finds the shortest path from a source to all other vertices in a weighted graph with non-negative edge weights. It uses a greedy approach by always selecting the unvisited vertex with minimum distance.
import java.util.*;public class Dijkstra {static class Edge {int to, weight;Edge(int to, int weight) {this.to = to;this.weight = weight;}}private List<Edge>[] adj;private int V;public Dijkstra(int V) {this.V = V;adj = new ArrayList[V];for (int i = 0; i < V; i++) {adj[i] = new ArrayList<>();}}public void addEdge(int u, int v, int weight) {adj[u].add(new Edge(v, weight));adj[v].add(new Edge(u, weight));}// Dijkstra's algorithmpublic int[] dijkstra(int source) {int[] distance = new int[V];boolean[] visited = new boolean[V];// Initialize distancesArrays.fill(distance, Integer.MAX_VALUE);distance[source] = 0;// Use priority queue for efficiencyPriorityQueue<Integer> pq = new PriorityQueue<>((u, v) -> Integer.compare(distance[u], distance[v]));pq.add(source);while (!pq.isEmpty()) {int u = pq.poll();if (visited[u]) continue;visited[u] = true;// Relax edgesfor (Edge edge : adj[u]) {int v = edge.to;int weight = edge.weight;if (distance[u] + weight < distance[v]) {distance[v] = distance[u] + weight;pq.add(v);}}}return distance;}public static void main(String[] args) {Dijkstra g = new Dijkstra(5);g.addEdge(0, 1, 4);g.addEdge(0, 2, 2);g.addEdge(1, 2, 1);g.addEdge(1, 3, 5);g.addEdge(2, 3, 8);g.addEdge(2, 4, 10);g.addEdge(3, 4, 2);int[] distances = g.dijkstra(0);System.out.println("Shortest distances from 0:");for (int i = 0; i < distances.length; i++) {System.out.println(" to " + i + ": " + distances[i]);}}}
Time Complexity
O((V + E) log V) with binary heap
O(V²) with simple array implementation
Requirements
Non-negative edge weights only
2. Bellman-Ford Algorithm
Bellman-Ford finds shortest paths even with negative edge weights. It's slower than Dijkstra but more versatile. It can also detect negative cycles.
public class BellmanFord {static class Edge {int u, v, weight;Edge(int u, int v, int weight) {this.u = u;this.v = v;this.weight = weight;}}private List<Edge> edges;private int V, E;public BellmanFord(int V) {this.V = V;edges = new ArrayList<>();}public void addEdge(int u, int v, int weight) {edges.add(new Edge(u, v, weight));}// Bellman-Ford algorithmpublic int[] bellmanFord(int source) {int[] distance = new int[V];Arrays.fill(distance, Integer.MAX_VALUE);distance[source] = 0;// Relax edges V-1 timesfor (int i = 0; i < V - 1; i++) {for (Edge edge : edges) {if (distance[edge.u] != Integer.MAX_VALUE &&distance[edge.u] + edge.weight < distance[edge.v]) {distance[edge.v] = distance[edge.u] + edge.weight;}}}// Check for negative cyclesfor (Edge edge : edges) {if (distance[edge.u] != Integer.MAX_VALUE &&distance[edge.u] + edge.weight < distance[edge.v]) {System.out.println("Negative cycle detected!");return null;}}return distance;}public static void main(String[] args) {BellmanFord g = new BellmanFord(5);g.addEdge(0, 1, 4);g.addEdge(0, 2, 2);g.addEdge(1, 2, -3); // Negative edgeg.addEdge(1, 3, 5);g.addEdge(2, 3, 8);int[] distances = g.bellmanFord(0);if (distances != null) {System.out.println("Shortest distances: " + Arrays.toString(distances));}}}
Time Complexity
O(VE) - slower but more flexible
Advantages
Handles negative weights, detects negative cycles
3. Floyd-Warshall Algorithm
Floyd-Warshall finds shortest paths between all pairs of vertices. It's useful when you need distances from every vertex to every other vertex.
public class FloydWarshall {private static final int INF = Integer.MAX_VALUE / 2;private int[][] dist;private int V;public FloydWarshall(int V) {this.V = V;dist = new int[V][V];// Initializefor (int i = 0; i < V; i++) {for (int j = 0; j < V; j++) {if (i == j) {dist[i][j] = 0;} else {dist[i][j] = INF;}}}}public void addEdge(int u, int v, int weight) {dist[u][v] = weight;}// Floyd-Warshall: All pairs shortest pathpublic void floydWarshall() {// For each intermediate vertexfor (int k = 0; k < V; k++) {// For each pair of verticesfor (int i = 0; i < V; i++) {for (int j = 0; j < V; j++) {// If path through k is shorterif (dist[i][k] + dist[k][j] < dist[i][j]) {dist[i][j] = dist[i][k] + dist[k][j];}}}}}public int getDistance(int u, int v) {return dist[u][v] == INF ? -1 : dist[u][v];}public static void main(String[] args) {FloydWarshall g = new FloydWarshall(4);g.addEdge(0, 1, 5);g.addEdge(0, 3, 10);g.addEdge(1, 2, 3);g.addEdge(2, 3, 1);g.floydWarshall();System.out.println("All pairs shortest paths:");for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {int d = g.getDistance(i, j);System.out.print(d >= 0 ? d + " " : "- ");}System.out.println();}}}
Time Complexity
O(V³) - slower but solves all-pairs problem
Use When
Need distances between all pairs of vertices
Algorithm Comparison
| Algorithm | Time | Negative Weights | All Pairs | Best For |
|---|---|---|---|---|
| Dijkstra | O((V+E)log V) | No | Single source | Most cases |
| Bellman-Ford | O(VE) | Yes | Single source | Negative weights |
| Floyd-Warshall | O(V³) | Yes | Yes | Small graphs, all pairs |
Algorithm Selection Guide
Use Dijkstra if
- No negative weights
- Need shortest path from one source
- Graph is large and sparse
Use Bellman-Ford if
- Graph has negative edge weights
- Need to detect negative cycles
- Willing to accept O(VE) complexity
Use Floyd-Warshall if
- Need all pairs shortest paths
- Graph is small (V < 500)
- Simplicity more important than speed
Key Takeaways
- Dijkstra's is the standard choice for non-negative weighted graphs
- Use priority queue for efficient Dijkstra implementation
- Bellman-Ford handles negative weights but slower
- Floyd-Warshall solves all-pairs problem but O(V³)
- Choose algorithm based on problem constraints
- Understanding shortest path algorithms is crucial for many applications