Dijkstra的最长路径算法

时间:2017-05-01 14:46:09

标签: java algorithm computer-science graph-algorithm dijkstra

编辑2:这可能为时已晚,但我想出了问题,就是我。我误解了这个项目,它要求最大的带宽路径不是最长的路径。这是不同的,但直到现在我都不知道。因此,基本上在任何带宽路径问题(无论是最大还是最小)中,权重都不会累积,路径值由路径中的最小权重确定。将其视为管道的路径,水流量由沿路径最深的管道确定。

编辑1:我修正了PQ问题,但仍无效。

这是一项任务(我承认),但如果我不提交,我可能会失败整个课程。我们应该修改Dijkstra算法来计算最长的SIMPLE路径而不是最短路径。我无法找到解决方案。我搜索了互联网并找到https://msdn.microsoft.com/en-us/library/chh3fb0k.aspx(这甚至是同样的问题)。

但是当我运行它时,它会产生不正确的值。我有什么遗失的东西吗?为什么它与前身的重量相加呢?为什么要使用min?

有关图表的信息:  我们随机生成图形,以便每个节点都连接到     大约25%的其他节点。  2.权重是积极的。  3.图中有25个节点。

问题是"路由算法是在图中查找最大带宽路径的算法。它基于使用Max-Heap结构修改Dijkstra算法"。是否有任何可能有帮助的技巧?

public class MaxDijkstra {
    Graph graph;
    PriorityQueue<Node> queue;

    public MaxDijkstra(Graph graph, Node s){
        this.graph = graph;
        s.addAttribute("ui.class", "start");
        queue = new PriorityQueue<>(new Comparator<Node>(){
            @Override
            public int compare(Node n1, Node n2) {
                if(Utils.getNodeBW(n1) == Utils.getNodeBW(n2)){
                    return 0;
                }else if(Utils.getNodeBW(n1) < Utils.getNodeBW(n2)){
                    return 1;
                }else{
                    return -1;
                }
            }
        });

        // init
        for(Node n : graph){
            Utils.setNodeBW(n, 0);
        }
        Utils.setNodeBW(s, Float.POSITIVE_INFINITY);

        // add to Q
        for(Node n : graph){
            queue.add(n);
        }

        while(!queue.isEmpty()){
            Node u = queue.remove();
            Iterator<Node> iterator = u.getNeighborNodeIterator();
            while(iterator.hasNext()){
                Node v = iterator.next();
                float min = Float.min(Utils.getNodeBW(u), Utils.getEdgeBW(u.getEdgeBetween(v)));
                if(min > Utils.getNodeBW(v)){
                    Utils.setNodeBW(v, min);
                    Utils.setPreOfNode(v, u);
                }
            }

            // validate PQ
            // I know it is not good, just for debuggin now
            // I will implemnt my own PQ later
            List<Node> list = new ArrayList<>();
            while(!queue.isEmpty()){
                Node w = queue.remove();
                list.add(w);
            }
            for(Node w : list){
                queue.add(w);
            }
        }
    }

    public void printInfo(){
        for(Node n : graph){
            System.out.println("N="+n.getId()+" D="+Utils.getNodeBW(n)+" pre="+ (Utils.getPreOfNode(n) == null ? "NIL" : Utils.getPreOfNode(n).getId()) );
        }
    }

    /**
     * Just to colourise the path
     * @param target 
     */
    public void backtrack(Node target){
        target.addAttribute("ui.class", "end");
        Node currunt = target;
        Node pre = Utils.getPreOfNode(currunt);
        while(pre != null){
            currunt.getEdgeBetween(pre).addAttribute("ui.class", "route");
            currunt = pre;
            pre = Utils.getPreOfNode(currunt);
        }
    }

示例输出: this

提前谢谢大家。

3 个答案:

答案 0 :(得分:3)

您无法使用Dijkstra算法找到最长的简单路径。这个问题是NP难的。事实上,没有已知的多项式解决方案。

如果图形相对较小,则可以使用动态编程来获得O(2^n * poly(n))解,这对于n~20-30是可行的(状态是访问顶点和最后一个顶点的掩码。转换是如果可能的话,添加一个顶点。

如果图形很大,您可以使用不同的启发式和近似值与局部优化技术相结合来获得一个好的(但不一定是最优的)解决方案。

答案 1 :(得分:0)

尝试将所有权重乘以-1以使所有权重为负。然后你可以使用Floyd-Warshall算法。 Floyd-Warshall算法在没有周期的图中使用负权重。因此,使用Floyd-Warshall查找最小路径,当乘以-1时,将是原始图形中的最大路径。

答案 2 :(得分:0)

您无法更改优先级队列中已有的元素。 通常对于Dijkstra,您需要decrease key函数,但库中的函数不支持,因此您可以使用不同的BW值将节点多次重新插入到pq中。像这样的东西(把它当作伪代码:))

    PriorityQueue<pair<Node, int>> queue;

    public MaxDijkstra(Graph graph, Node s){

        queue = new PriorityQueue<>(new Comparator<pair<Node, int>>(){
            @Override
            public int compare(pair<Node, int> n1, pair<Node, int> n2) {
                return n1.second > n2.second;
            }
        });

        // init
        for(Node n : graph){
            Utils.setNodeBW(n, 0);
        }
        Utils.setNodeBW(s, Integer.MAX_VALUE);

        // add to Q
        for(Node n : graph){
            queue.add({n, n.getNodeBW()});
        }

        while(!queue.isEmpty()){
            pair<Node, int> u = queue.remove();
            if (u.second < u.first.getNodeBW()) continue; //important - skip if you already saw better value
            Iterator<Node> iterator = u.getNeighborNodeIterator();
            while(iterator.hasNext()){
                Node v = iterator.next();
                int min = Integer.min(Utils.getNodeBW(u), Utils.getEdgeBW(u.getEdgeBetween(v)));
                if(min > Utils.getNodeBW(v)){
                    Utils.setNodeBW(v, min);
                    queue.insert({v, min});
                }
            }
        }
    }
}