【问题标题】:Setting vertex weight with Dijkstra's shortest path algorithm使用 Dijkstra 的最短路径算法设置顶点权重
【发布时间】:2018-05-23 08:15:26
【问题描述】:

Java 新手。

我正在尝试制作一个代表城市的有向图。大多数顶点只是街道,但有些是具有权重的旅游景点(因为必须在那里停留一段时间)。我正在使用 Dijkstra 的 最短路径算法,并制作了一些版本来添加顶点的权重。

但是,当我将一个顶点设置为旅游站点并赋予它权重时,会出现问题,该顶点在第一次访问时似乎根本没有权重。当第二次访问顶点时,权重就会出现。我不知道问题出在哪里,但我会这是我没有直接编辑原始变量的地方。

打印输出的行在下面的 * * 之间标记。一个在 calculateShortest() 中,另一个在 calculateMin() 中。

public class Graph
{
    protected HashMap<Integer, GraphNode> ntable = new HashMap<Integer, GraphNode>();
    //a hashmap of every node's edge treemap, in which edges are sorted according to weight of each
    protected HashMap<Integer, TreeMap<Integer, GraphEdge>> etable = new HashMap<Integer, TreeMap<Integer,GraphEdge>>();
}

public class GraphNode
{
    private int val;
    private boolean site;
    private boolean hotel;
    private int time;
    private int distance = Integer.MAX_VALUE;
    private LinkedList<GraphNode> shortest = new LinkedList<GraphNode>();
}

public class GraphEdge implements Comparable<GraphEdge>
{
    private int nd1;
    private int nd2;
    private int weight;
}

public class Path
{
    protected LinkedList<GraphNode> path = new LinkedList<GraphNode>();
    Graph g = new Graph();
    GraphNode start = new GraphNode(0);
    protected HashSet<GraphNode> settled = new HashSet<GraphNode>();
    protected HashSet<GraphNode> unsettled = new HashSet<GraphNode>();

    public Graph calculateShortest(int start)
    {
        g.ntable.get(start).setDist(0);
        unsettled.add(g.ntable.get(start));
        while (unsettled.size() != 0)
        {
            GraphNode current = getLowestCostNode(unsettled);
            unsettled.remove(current);
            TreeMap<Integer, GraphEdge> adjacentE = g.etable.get(current.getVal());
            *
           //printing out below shows vertex has no weight
            System.out.println("Curr: "+ current.getVal() + " " + current.getSiteTime());
            *
            for (GraphEdge edge: adjacentE.values())
            {
                GraphNode adjacent = g.ntable.get(edge.getEnd());
                int cost = edge.getWeight() + current.getSiteTime();
                if (!settled.contains(adjacent))
                {
                    calculateMin(adjacent, cost, current);
                    unsettled.add(adjacent);
                }
            }
            settled.add(current);
        }
    return g;
}

    public GraphNode getLowestCostNode(HashSet<GraphNode> unsettled)
    {
        GraphNode lowestDistNd = null;
        int lowestDist = Integer.MAX_VALUE;
        for (GraphNode nd : unsettled)
        {
            int nodeDist = nd.getDist();
            if (nodeDist < lowestDist)
            {
                lowestDist = nodeDist;
                lowestDistNd = nd;
            }
        }
        return lowestDistNd;
    }

    public void calculateMin(GraphNode evaNd, int cost, GraphNode startNd)
    {
        int startDist = startNd.getDist();
        if (startDist + cost < evaNd.getDist())
        {
            evaNd.setDist(startDist + cost);
            LinkedList<GraphNode> shortest = new LinkedList<GraphNode>(startNd.getShortest());
            shortest.add(startNd);
            evaNd.setShortest(shortest);
            *
            //print out if the node's distance is changed
            System.out.println("Change " + evaNd.getVal() + " " + evaNd.getDist());
            *
        }
    }
}

显示问题的行打印输出(不包括main方法输出):

Curr: 1 0
Change: 2 10
Change: 3 15
Curr: 2 0
Change: 4 22
Change: 6 25
Curr: 3 0
Change: 5 25
Curr: 4 0 //1st time visiting shows no weight
Change: 6 23
Change: 5 24
Curr: 6 0
Curr: 5 0
Curr: 1 0
Curr: 2 0
Curr: 3 0
Curr: 4 30 //2nd time visiting shows weight
Curr: 6 0
Curr: 5 0

对于每个顶点,getDist()返回源顶点到自身的距离,getCost()返回距离加上权重 的顶点。

我的主要方法如下。 addNodeEdge() 已经过测试可以正常工作。我正在使用来自Dijkstra Algorithm in Java示例(见下图),在我的情况下 ABCDEF 是 123456。除了图表,我试图将 D(即顶点 4)设为权重为 30 的站点Visualization of the graph

public static void main (String [] args){
    Path p = new Path();
    p.g.addNodeEdge(1, 2, 10);
    p.g.addNodeEdge(1, 3, 15);
    p.g.addNodeEdge(2, 4, 12);
    p.g.addNodeEdge(2, 6, 15);
    p.g.addNodeEdge(3, 5, 10);
    p.g.addNodeEdge(4, 6, 1);
    p.g.addNodeEdge(4, 5, 2);
    p.g.addNodeEdge(6, 5, 5); 
    p.calculateShortest(1);
    System.out.println(p.g.ntable.get(5).getDist());//print out 24

    p.settled.clear();
    p.unsettled.clear();
    p.g.ntable.get(4).setSite(30);
    p.calculateShortest(1);  
    System.out.println(p.g.ntable.get(5).getDist());//still print out 24
}

我希望到 E(顶点 5)30 和 F(顶点 6)25 的最短路径,因为通过 D(顶点 4)的路径,权重为 30 太大。然而,我改变 D 的权重后得到的结果与我为 D 增加权重之前完全相同。就像我上面解释的那样,我认为问题在于 D 的体重变化......任何帮助将不胜感激。

【问题讨论】:

    标签: graph path shortest-path dijkstra vertex


    【解决方案1】:

    即使您正在清除已确定和未确定的 HashSet,跟踪迄今为止找到的节点的最短路径的变量是 GraphNode 实例变量距离。节点 5 的距离在第一次运行 calculateShortest 后不会从 24 的值重置,当然在将节点 4 的站点时间设置为 30 后调用该方法后会保持不变。

    一种可能的解决方案是更改 calculateShortest() 的开头以重置所有节点距离:

    public Graph calculateShortest(int start) {
        for (GraphNode n : g.ntable.values()) {
            n.setDist(Integer.MAX_VALUE);
        }
        g.ntable.get(start).setDist(0);
        ...
    

    另外,解决这个问题需要一些时间,主要是因为您发布的代码格式很差。下次请避免发布嵌套类,并包括所有潜在相关的实现细节,这些细节不是微不足道的 getter/setter(例如 addNodeEdge)。你永远不知道那个讨厌的虫子可能藏在哪里!

    【讨论】:

    • 非常感谢!!!它奏效了……那是一个非常粗心的错误。而且它们实际上不是嵌套类大声笑......我没有把类的最后花括号放在那里......抱歉造成混乱!
    • 没问题,很高兴为您提供帮助。请注意,如果它回答了您的问题,请确保接受答案,而不是继续发表评论!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    • 1970-01-01
    • 2016-07-30
    • 2021-04-18
    相关资源
    最近更新 更多