package com.thealgorithms.datastructures.graphs;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang3.tuple.Pair;
/**
* Dijkstra's algorithm for finding the shortest path from a single source vertex to all other vertices in a graph.
*/
public class DijkstraOptimizedAlgorithm {
private final int vertexCount;
/**
* Constructs a Dijkstra object with the given number of vertices.
*
* @param vertexCount The number of vertices in the graph.
*/
public DijkstraOptimizedAlgorithm(int vertexCount) {
this.vertexCount = vertexCount;
}
/**
* Executes Dijkstra's algorithm on the provided graph to find the shortest paths from the source vertex to all other vertices.
*
* The graph is represented as an adjacency matrix where {@code graph[i][j]} represents the weight of the edge from vertex {@code i}
* to vertex {@code j}. A value of 0 indicates no edge exists between the vertices.
*
* @param graph The graph represented as an adjacency matrix.
* @param source The source vertex.
* @return An array where the value at each index {@code i} represents the shortest distance from the source vertex to vertex {@code i}.
* @throws IllegalArgumentException if the source vertex is out of range.
*/
public int[] run(int[][] graph, int source) {
if (source < 0 || source >= vertexCount) {
throw new IllegalArgumentException("Incorrect source");
}
int[] distances = new int[vertexCount];
boolean[] processed = new boolean[vertexCount];
Set<Pair<Integer, Integer>> unprocessed = new TreeSet<>();
Arrays.fill(distances, Integer.MAX_VALUE);
Arrays.fill(processed, false);
distances[source] = 0;
unprocessed.add(Pair.of(0, source));
while (!unprocessed.isEmpty()) {
Pair<Integer, Integer> distanceAndU = unprocessed.iterator().next();
unprocessed.remove(distanceAndU);
int u = distanceAndU.getRight();
processed[u] = true;
for (int v = 0; v < vertexCount; v++) {
if (!processed[v] && graph[u][v] != 0 && distances[u] != Integer.MAX_VALUE && distances[u] + graph[u][v] < distances[v]) {
unprocessed.remove(Pair.of(distances[v], v));
distances[v] = distances[u] + graph[u][v];
unprocessed.add(Pair.of(distances[v], v));
}
}
}
return distances;
}
}