Я тоже сталкивался с той же проблемой (если я правильно отношусь к вашей) - все хорошо, пока вершина нашего происхождения не станет той вершиной, где мы можем достичь всех других вершин в ориентированном графе. Проблема начинается, когда мы выбрали исходную вершину, где мы не можем достичь всех других вершин в том же ориентированном графе. ex -
2 4 1
A---->B--------->C----->D
| \ | \ |
7 | \9 13| 3\ |6
| \ | \ |
v v v vv
E---->F--------->G----->H
1 8 13
Выше, если мы выбрали вершину A, которая может достигать всех других вершин, т.е. B, C, D, E, FG & H - наш код в основном работает нормально. Но если мы выбрали вершину C, из которой мы можем добраться только до D, G & H выше. Проблема начнется, как когда мы извлечем Item для других недостижимых вершин B, C, E & F как минимальный элемент из нашего приоритета QUEUE, чтобы поместить их в окончательный набор / список кратчайших путей. Эти элементы будут иметь нереалистичное расстояние c в наборе / списке кратчайших путей, поскольку они не достижимы с C. Далее, когда мы проследим этот набор / список кратчайших путей для исходной вершины C в другие вершины, чтобы напечатать кратчайший путь, мы получим неверную информацию, поскольку недостижимые вершины также являются частью нашего окончательного набора / списка кратчайших путей.
Таким образом, решение состоит в том, чтобы ограничить запись элемента в окончательном наборе / списке, извлеченном из нашей очереди приоритетов, если этот элемент имеет нереалистичное расстояние c. Я проиллюстрировал этот код следующим образом -
Проверьте код в строке комментария ниже, который ограничивает любую недостижимую вершину, как если бы расстояние было нереальным c до нашего окончательного списка путей. // Ограничить доступ к элементам, имеющим нереалистичные значения c расстояния пути
package com.company.graph;
import java.util.*;
public class ShortestPath_Dijkstra {
public static void main(String...args){
String directedGraph =
"\n\n 2 4 1\n" +
" A---->B--------->C----->D\n" +
" | \\ | \\ |\n" +
" 7 | \\9 13| 3\\ |6\n" +
" | \\ | \\ |\n" +
" v v v vv\n" +
" E---->F--------->G----->H\n" +
" 1 8 13" ;
// We store number instated of letters since in real world every vertex may have full qualified name ex - "LasVegas" instead of just "A"
Map<Integer,String> vertices = new HashMap<>();
vertices.put(0,"A");
vertices.put(1,"B");
vertices.put(2,"C");
vertices.put(3,"D");
vertices.put(4,"E");
vertices.put(5,"F");
vertices.put(6,"G");
vertices.put(7,"H");
Map<Edge, Integer> edges = new HashMap<>();
//Implemented edges as a Map where for each entry - key is a vertex and value is List containing edges i.e. all connecting vertices along with the weight !!
Map<Integer, List<Edge>> verticesEdges = new HashMap<>();
verticesEdges.put(0, new LinkedList<>(List.of(new Edge(1,2), new Edge(4,7),new Edge(5,9) )));
verticesEdges.put(1, new LinkedList<>(List.of(new Edge(2,4))));
verticesEdges.put(2, new LinkedList<>(List.of(new Edge(3,1),new Edge(6,13), new Edge(7,3))));
verticesEdges.put(3, new LinkedList<>(List.of(new Edge(7,6))));
verticesEdges.put(4, new LinkedList<>(List.of(new Edge(5,1) )));
verticesEdges.put(5, new LinkedList<>(List.of(new Edge(6,8) )));
verticesEdges.put(6, new LinkedList<>(List.of(new Edge(7,13))));
verticesEdges.put(7, new LinkedList<>());
Integer origin = 2; // alias C
Map<Integer, Item> pathMap = getShortestPathMap(origin, vertices, verticesEdges);
displayShortestPaths(directedGraph, origin, pathMap, vertices);
}
//Dijkstra function
static Map<Integer, Item> getShortestPathMap(Integer origin, Map<Integer,String> vertices, Map<Integer, List<Edge>> verticesEdges){
Map<Integer, Item> pathMap = new HashMap<>();
PriorityQueue<Item> queue = new PriorityQueue<>();
//Initialization of queue.
vertices.keySet().forEach(v -> {
if(v.equals(origin)){
queue.add(new Item(v, 0, null));
}else {
queue.add(new Item(v));
}
});
while(!queue.isEmpty()){
Item currItem = queue.poll();
//Restrict entry of Items having unrealistic path distances
if(currItem.getDistance() != Integer.MAX_VALUE && currItem.getDistance() >= 0){
pathMap.put(currItem.vertex, currItem);
}
verticesEdges.get(currItem.getVertex()).forEach(edge -> {
//Get item in queue corresponding to vertex of this edge
Item connItem = new Item(edge.getV());
Iterator<Item> iterator = queue.iterator();
boolean found = false;
while(iterator.hasNext()){
Item inQueue = iterator.next();
if(inQueue.equals(connItem)){
connItem = inQueue;
found = true;
break;
}
}
//Update this connection Item distance if more than sum distance of current vertex and connecting edge weight. And also parent as current vertex.
if(found && connItem.getDistance() > currItem.getDistance() + edge.getW()){
queue.remove(connItem);
queue.add(new Item(connItem.getVertex(), currItem.getDistance() + edge.getW(), currItem.getVertex()));
}
});
}
return pathMap;
}
//Display function
static void displayShortestPaths(String directedGraph, Integer origin, Map<Integer, Item> pathMap, Map<Integer,String> vertices){
System.out.println("For a directed Graph - " + directedGraph );
System.out.format("%nShortest Paths to all vertices starting from %S - %n", vertices.get(origin));
vertices.keySet().forEach(v ->{
if(pathMap.get(v)!=null){
System.out.format("%n Shortest path(distance) from %S --> %S is %S", vertices.get(origin), vertices.get(v), pathMap.get(v).getDistance());
System.out.format(" via vertices : ");
Stack<String> path = new Stack<>();
path.push(vertices.get(v));
while(pathMap.get(v).getParent() != null){
v = pathMap.get(v).getParent();
path.push(vertices.get(v));
}
System.out.format("%S", path.pop());
while (!path.empty()){
System.out.format("-->%S", path.pop());
}
}
});
}
// Below class are Data Structures to store and process graph
static class Edge {
Integer v; //Connecting Vertex
Integer w; //weight Of edge
Edge(int v, int w) {
this.v = v;
this.w = w;
}
int getV() { return v; }
int getW() { return w; }
}
static class Item implements Comparable<Item>{
Integer vertex;
Integer distance = Integer.MAX_VALUE;
Integer parent = null;
Item(Integer vertex) {
this.vertex = vertex;
}
Item(Integer vertex, Integer distance, Integer parent) {
this.vertex = vertex;
this.distance = distance;
this.parent = parent;
}
Integer getVertex() { return vertex; }
Integer getDistance() { return distance; }
Integer getParent() { return parent; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item item = (Item) o;
return vertex.equals(item.vertex);
}
@Override
public int hashCode() {
return Objects.hash(vertex);
}
@Override
public int compareTo(Item item) {
return this.distance - item.distance;
}
}
}
Давайте запустим приведенный выше код, я полагаю, чтобы увидеть только кратчайшие расстояния до достижимых вершин из C не любые нереалистичные c (недостижимые) -
For a directed Graph -
2 4 1
A---->B--------->C----->D
| \ | \ |
7 | \9 13| 3\ |6
| \ | \ |
v v v vv
E---->F--------->G----->H
1 8 13
Shortest Paths to all vertices starting from C -
Shortest path(distance) from C --> C is 0 via vertices : C
Shortest path(distance) from C --> D is 1 via vertices : C-->D
Shortest path(distance) from C --> G is 13 via vertices : C-->G
Shortest path(distance) from C --> H is 3 via vertices : C-->H
Process finished with exit code 0
Давайте также проверим, что «если условие» для ограничения нереалистичных c записей не оказало негативного влияния на случай, когда вершина A является исходной (т. е. все остальные вершины в графе достижимы) - для этого нам нужно сделать 1 замену строки, чтобы сказать, что исходная вершина теперь A,
Integer origin = 0; // alias A
For a directed Graph -
2 4 1
A---->B--------->C----->D
| \ | \ |
7 | \9 13| 3\ |6
| \ | \ |
v v v vv
E---->F--------->G----->H
1 8 13
Shortest Paths to all vertices starting from A -
Shortest path(distance) from A --> A is 0 via vertices : A
Shortest path(distance) from A --> B is 2 via vertices : A-->B
Shortest path(distance) from A --> C is 6 via vertices : A-->B-->C
Shortest path(distance) from A --> D is 7 via vertices : A-->B-->C-->D
Shortest path(distance) from A --> E is 7 via vertices : A-->E
Shortest path(distance) from A --> F is 8 via vertices : A-->E-->F
Shortest path(distance) from A --> G is 16 via vertices : A-->E-->F-->G
Shortest path(distance) from A --> H is 9 via vertices : A-->B-->C-->H
Process finished with exit code 0