83 lines
3.1 KiB
Java
83 lines
3.1 KiB
Java
|
package com.jwetherell.algorithms.graph;
|
|||
|
|
|||
|
import java.util.HashMap;
|
|||
|
import java.util.List;
|
|||
|
import java.util.Map;
|
|||
|
|
|||
|
import com.jwetherell.algorithms.data_structures.Graph;
|
|||
|
|
|||
|
/**
|
|||
|
* Floyd–Warshall algorithm is a graph analysis algorithm for finding shortest
|
|||
|
* paths in a weighted graph (with positive or negative edge weights).
|
|||
|
*
|
|||
|
* Worst case: O(V^3)
|
|||
|
*
|
|||
|
* https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
|
|||
|
*
|
|||
|
* @author Justin Wetherell <phishman3579@gmail.com>
|
|||
|
*/
|
|||
|
public class FloydWarshall {
|
|||
|
|
|||
|
private FloydWarshall() { }
|
|||
|
|
|||
|
public static Map<Graph.Vertex<Integer>, Map<Graph.Vertex<Integer>, Integer>> getAllPairsShortestPaths(Graph<Integer> graph) {
|
|||
|
if (graph == null)
|
|||
|
throw (new NullPointerException("Graph must be non-NULL."));
|
|||
|
|
|||
|
final List<Graph.Vertex<Integer>> vertices = graph.getVertices();
|
|||
|
|
|||
|
final int[][] sums = new int[vertices.size()][vertices.size()];
|
|||
|
for (int i = 0; i < sums.length; i++) {
|
|||
|
for (int j = 0; j < sums[i].length; j++) {
|
|||
|
sums[i][j] = Integer.MAX_VALUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
final List<Graph.Edge<Integer>> edges = graph.getEdges();
|
|||
|
for (Graph.Edge<Integer> e : edges) {
|
|||
|
final int indexOfFrom = vertices.indexOf(e.getFromVertex());
|
|||
|
final int indexOfTo = vertices.indexOf(e.getToVertex());
|
|||
|
sums[indexOfFrom][indexOfTo] = e.getCost();
|
|||
|
}
|
|||
|
|
|||
|
for (int k = 0; k < vertices.size(); k++) {
|
|||
|
for (int i = 0; i < vertices.size(); i++) {
|
|||
|
for (int j = 0; j < vertices.size(); j++) {
|
|||
|
if (i == j) {
|
|||
|
sums[i][j] = 0;
|
|||
|
} else {
|
|||
|
final int ijCost = sums[i][j];
|
|||
|
final int ikCost = sums[i][k];
|
|||
|
final int kjCost = sums[k][j];
|
|||
|
final int summed = (ikCost != Integer.MAX_VALUE &&
|
|||
|
kjCost != Integer.MAX_VALUE) ?
|
|||
|
(ikCost + kjCost)
|
|||
|
:
|
|||
|
Integer.MAX_VALUE;
|
|||
|
if (ijCost > summed)
|
|||
|
sums[i][j] = summed;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
final Map<Graph.Vertex<Integer>, Map<Graph.Vertex<Integer>, Integer>> allShortestPaths = new HashMap<Graph.Vertex<Integer>, Map<Graph.Vertex<Integer>, Integer>>();
|
|||
|
for (int i = 0; i < sums.length; i++) {
|
|||
|
for (int j = 0; j < sums[i].length; j++) {
|
|||
|
final Graph.Vertex<Integer> from = vertices.get(i);
|
|||
|
final Graph.Vertex<Integer> to = vertices.get(j);
|
|||
|
|
|||
|
Map<Graph.Vertex<Integer>, Integer> map = allShortestPaths.get(from);
|
|||
|
if (map == null)
|
|||
|
map = new HashMap<Graph.Vertex<Integer>, Integer>();
|
|||
|
|
|||
|
final int cost = sums[i][j];
|
|||
|
if (cost != Integer.MAX_VALUE)
|
|||
|
map.put(to, cost);
|
|||
|
allShortestPaths.put(from, map);
|
|||
|
}
|
|||
|
}
|
|||
|
return allShortestPaths;
|
|||
|
}
|
|||
|
}
|