簡體   English   中英

計算無向加權圖中一組頂點之間的最短路徑

[英]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個節點的圖。 對於成千上萬個節點,不是那么多。

這要求您實現PathNode類。 這是它們的部分實現:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM