繁体   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