简体   繁体   English

Dijkstra的最长路径算法

[英]Dijkstra's algorithm for longest path

EDIT 2: This might be too late, but I figured out the problem, it was me. 编辑2:这可能为时已晚,但我想出了问题,就是我。 I misunderstood the project, it asked for the largest bandwidth path not the longest path. 我误解了这个项目,它要求最大的带宽路径不是最长的路径。 which is different but I didn't know until now. 这是不同的,但直到现在我才知道。 So basically in any bandwidth path problem (whether largest or smallest), the weights are not accumulated, the path value is determined by the smallest weight in the path. 因此,基本上在任何带宽路径问题(无论是最大还是最小)中,权重都不会累积,路径值由路径中的最小权重确定。 Think of it as a path of pipes and the water flow is determined by the thinest pipe along the path. 将其视为管道的路径,水流量由沿路径的最细管道决定。

EDIT 1: I fixed the PQ issue, but still not working. 编辑1:我修复了PQ问题,但仍无法正常工作。

It is an assignment (I admit), but I may fail the whole course if I don't submit it. 这是一项任务(我承认),但如果我不提交,我可能会失败整个课程。 We are supposed to modify Dijkstra's algorithm to calculate the longest SIMPLE path instead of the shortest path. 我们应该修改Dijkstra的算法来计算最长的SIMPLE路径而不是最短的路径。 I couldn't figure out a solution. 我无法找到解决方案。 I searched the Internet and found this (It is even the same problem). 我搜索了互联网,发现了这个问题 (甚至是同样的问题)。

But when I run it, it produces incorrect values. 但是当我运行它时,它会产生不正确的值。 Is there any thing I'm missing ? 有什么我想念的吗? Why even doesn't it sum the weight with the predecessor ? 为什么它甚至不能与前任相加呢? Why use min ? 为什么用min?

Info about the graph: 1. We generate the graph randomly such that each node is connected to about 25% of the other nodes. 有关图表的信息:1。我们随机生成图表,使每个节点连接到大约25%的其他节点。 2. Weights are positive. 2.权重是积极的。 3. There are 25 nodes in the graph. 3.图中有25个节点。

The question says "Routing Algorithm is the algorithm of finding maximum bandwidth path in a graph. It is based on modification of Dijkstra's algorithm using a Max-Heap structure". 问题是“路由算法是在图中找到最大带宽路径的算法。它基于使用Max-Heap结构修改Dijkstra算法”。 Is there any trick in it that may help ? 有什么技巧可以帮助吗?

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

Sample output: 样本输出: 不是最高带宽

Thank you all in advance. 谢谢大家。

You can't use Dijkstra's algorithm to find the longest simple path. 你不能使用Dijkstra的算法来找到最长的简单路径。 This problem is NP-hard. 这个问题是NP难的。 In fact, there's no known polynomial solution to it. 事实上,没有已知的多项式解决方案。

If the graph is relatively small, you can use dynamic programming to get an O(2^n * poly(n)) solution, which is feasible for n ~ 20-30 (the state is mask of visited vertices and the last vertex. A transition is adding one vertex if it's possible). 如果图形相对较小,则可以使用动态编程来获得O(2^n * poly(n))解,这对于n~20-30是可行的(状态是访问顶点的掩模和最后一个顶点。如果可能的话,转换是添加一个顶点)。

If the graph is large, you can use different heuristics and approximations combined with local optimization techniques to get a good (but not necessarily an optimal) solution. 如果图形很大,您可以使用不同的启发式和近似值与局部优化技术相结合来获得一个好的(但不一定是最优的)解决方案。

Try multiplying all weights by -1 to make all of the weights negative. 尝试将所有权重乘以-1以使所有权重为负。 Then you can use the Floyd-Warshall algorithm. 然后你可以使用Floyd-Warshall算法。 The Floyd-Warshall algorithm works with negative weights in a graph that doesn't have a cycle. Floyd-Warshall算法在没有循环的图中使用负权重。 So, use Floyd-Warshall to find the smallest path, which when multiplied by -1, will be your maximum path in the original graph. 因此,使用Floyd-Warshall查找最小路径,当乘以-1时,将是原始图形中的最大路径。

You can't alter elements already in the priority queue. 您无法更改优先级队列中已有的元素。 Normally for Dijkstra you need a decrease key function, but the one from the library doesn't support that, so you can just reinsert nodes multiple times into the pq with different BW values. 通常对于Dijkstra,您需要一个decrease key功能,但是库中的那个不支持,所以您可以使用不同的BW值将节点多次重新插入到pq中。 Something like this (regard this as pseudocode :)) 像这样的东西(认为这是伪代码:))

    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