简体   繁体   English

计算无向加权图中一组顶点之间的最短路径

[英]Calculate the shortest path between a set of vertices in an undirected weighted graph

I have an undirected weighted graph (G) composed of at least 15 vertices. 我有一个至少包含15个顶点的无向加权图(G)。 Given a set of vertices (G'), where G' ⊆ G, I need to calculate the shortest path required to traverse G' given a start vertex (v). 给定一组顶点(G'),其中G'⊆G,我需要计算在给定起始顶点(v)的情况下遍历G'所需的最短路径。 I am stuck! 我被卡住了! I tried the following: 我尝试了以下方法:

for (Vertex vx : G'):
    computeShortestPath (v, vx)//using Dijkstra's algo

The shortest of all the paths generated between V and any vertex from G' will then constitute the initialized path (P).I then remove all vertices from G' that have been visited in P 在V和G'的任何顶点之间生成的所有路径中最短的路径将构成初始化路径(P)。然后我从G'中移除所有在P中访问过的顶点

G'.remove (P)

Recursively compute P until: 递归计算P直到:

G'.size () == 0

My algorithm seems inefficient at times though! 我的算法有时似乎效率很低! Any suggestions into different remedies to this problem? 对这个问题有不同的补救措施有什么建议吗?

Edit: I need to visit every node in G' only once. 编辑:我只需要访问G'中的每个节点一次。

If I understand your problem correctly then it is, essentially, the Travelling Salesman problem which has been proven to be NP-hard: there is no efficient solution to this problem. 如果我正确地理解了您的问题,那么实质上就是旅行商问题,这已被证明是NP难题的:此问题没有有效的解决方案。 Any solution you come up with requires resources that increase exponentially with the number of nodes. 您想出的任何解决方案都需要随着节点数量成倍增加的资源。 There are efficient solutions for returning the most likely shortest path or to iterate towards the shortest path. 有返回最可能的最短路径或迭代到最短路径的有效解决方案。 There are algorithms for determining if there is a path before starting the search. 有一些算法可以在开始搜索之前确定是否存在路径。

Djikstra's algorithm is used to find the shortest path through the graph rather than the shortest path that visits all nodes. Djikstra的算法用于查找通过图形的最短路径,而不是访问所有节点的最短路径。

For small numbers of nodes the easiest solution is an exhaustive search of all paths. 对于少量节点,最简单的解决方案是穷举搜索所有路径。 This will look something like: 这看起来像:

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);
            }
        }
    }
}

This algorithm does not copy the path or list of remaining nodes for efficiency reasons. 出于效率考虑,此算法不会复制路径或剩余节点列表。 It will work find for graphs of 15 nodes. 它将找到15个节点的图。 For thousands of nodes not so much. 对于成千上万个节点,不是那么多。

This requires you to implement Path and Node classes. 这要求您实现PathNode类。 Here is a possible partial implementation of them: 这是它们的部分实现:

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