[英]Calculate the shortest path between a set of vertices in an undirected weighted graph
我有一個至少包含15個頂點的無向加權圖(G)。 給定一組頂點(G'),其中G'⊆G,我需要計算在給定起始頂點(v)的情況下遍歷G'所需的最短路徑。 我被卡住了! 我嘗試了以下方法:
for (Vertex vx : G'):
computeShortestPath (v, vx)//using Dijkstra's algo
在V和G'的任何頂點之間生成的所有路徑中最短的路徑將構成初始化路徑(P)。然后我從G'中移除所有在P中訪問過的頂點
G'.remove (P)
遞歸計算P直到:
G'.size () == 0
我的算法有時似乎效率很低! 對這個問題有不同的補救措施有什么建議嗎?
編輯:我只需要訪問G'中的每個節點一次。
如果我正確地理解了您的問題,那么實質上就是旅行商問題,這已被證明是NP難題的:此問題沒有有效的解決方案。 您想出的任何解決方案都需要隨着節點數量成倍增加的資源。 有返回最可能的最短路徑或迭代到最短路徑的有效解決方案。 有一些算法可以在開始搜索之前確定是否存在路徑。
Djikstra的算法用於查找通過圖形的最短路徑,而不是訪問所有節點的最短路徑。
對於少量節點,最簡單的解決方案是窮舉搜索所有路徑。 這看起來像:
class PathFinder {
Path shortestPath;
public void findShortestPath(Path currentPath, List<Node> remainingNodes) {
if (remainingNodes.isEmpty()) {
if (currentPath.isShorterThan(shortestPath)) {
shortestPath = currentPath;
}
} else {
for (Node node: currentPath.possibleNextNodes(remainingNodes)) {
remainingNodes.remove(node);
currentPath.add(node);
findShortestPath(currentPath, remainingNodes);
currentPath.remove(node);
remainingNodes.add(node);
}
}
}
}
出於效率考慮,此算法不會復制路徑或剩余節點列表。 它將找到15個節點的圖。 對於成千上萬個節點,不是那么多。
這要求您實現Path
和Node
類。 這是它們的部分實現:
public class Node {
private class Link {
private final Node destination;
private final int weight;
private Link(Node destination, int weight) {
this.destination = destination;
this.weight = weight;
}
private final List<Link> links;
public void addLink(Node destination, int weight) {
if (!connectsTo(destination)) {
Link link = new Link(destination, weight);
destination.addLink(this, weight);
}
}
public boolean connectsTo(Node node) {
return links.stream.anyMatch(link -> link.destination.equals(node));
}
public int weightTo(Node node) {
return links.stream.filter(link -> link.destination.equals(node))
.findAny().orElse(0);
}
}
public class Path {
private int length;
private List<Node> nodes;
private Node lastNode() {
return nodes.get(nodes.size() - 1);
}
public List<Node> possibleNextNodes(List<Node> possibleNodes) {
if (nodes.isEmpty());
return possibleNodes;
return possibleNodes.stream()
.filter(node -> lastNode().connectsTo(node))
.filter(node -> !nodes.contains(node))
.collect(Collectors.toList());
}
public boolean isShorterThan(Path other) {
return this.length < other.length;
}
public void add(Node node) {
length += lastNode().distanceTo(node);
nodes.add(node);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.