繁体   English   中英

Dijkstra的最长路径算法

[英]Dijkstra's algorithm for longest path

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

编辑1:我修复了PQ问题,但仍无法正常工作。

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

但是当我运行它时,它会产生不正确的值。 有什么我想念的吗? 为什么它甚至不能与前任相加呢? 为什么用min?

有关图表的信息:1。我们随机生成图表,使每个节点连接到大约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);
        }
    }

样本输出: 不是最高带宽

谢谢大家。

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

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

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

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

您无法更改优先级队列中已有的元素。 通常对于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});
                }
            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM