如何用给定的参数计算Graph中两个顶点之间的最短路径?

时间:2016-11-03 14:29:46

标签: java algorithm graph shortest-path dijkstra

我们需要计算 minCost(),其中包含以下参数:

  1. gNodes - 图g中没有节点。
  2. 一个int的数组, gFrom ,其中每个gfrom [i]表示由图g中的 ith 边连接的节点。
  3. 一个int的数组, gTo ,其中每个gTo [i]表示由图g中的 ith 边连接的节点。
  4. 一个int的数组, gWeight ,表示图g中每条边的相应权重。
  5. 一个int,开始,表示起始节点索引。
  6. 一个int,结束,表示结束节点索引。
  7. 一个整数, wExtra ,表示可选额外边缘的权重。
  8. 我们需要找到从头到尾具有最小可能重量的路径。我们可以在任意两个未被边连接的不同节点之间添加一个额外的边(即零或一个) wExtra 权重。该函数必须返回一个int,表示从开始到结束的最小路径权重。

    我能够提出以下代码(Dijkstra算法),但它没有给出预期的输出。

        public static int minCost(int gNodes, int[] gFrom, int[] gTo, int[] gWeights, int start, int end) {
    //making a array to store shortest length and filling it with infinity except the first one
                int[] shortest = new int[gNodes];
                for (int i = 0; i < gNodes; i++) {
                    shortest[i] = Integer.MAX_VALUE;
                }
                shortest[start]=0;
    //filling the Queue with all vertices
            Queue<Integer> theQ = new PriorityQueue<>();
            for (int i = 0; i < gNodes; i++) {
                theQ.add(i + 1);
            }
    //following the algorithm
            while (!theQ.isEmpty()) {
                int u = theQ.poll();
    //making a list of adjacent vertices
    
                List<Integer> adjacent = new ArrayList<>();
                for (int i = 0; i < gFrom.length; i++) {
                    if (gFrom[i] == u) {
                        adjacent.add(gTo[i]);
                    } else if (gTo[i] == u) {
                        adjacent.add(gFrom[i]);
                    }
                }
                for (int v: adjacent) {
                    int weight=0;
                    for (int i = 0; i < gFrom.length; i++) {
                        if ((gFrom[i] == u && gTo[i] == v) || (gFrom[i] == v && gTo[i] == u)) {
                            weight = gWeights[i];
                        }
                    }
    
    //relaxing the verices
                    if (shortest[v] > shortest[u] + weight) {
                        shortest[v] = shortest[u] + weight;
                    }
                    if (v == end) {
                        return shortest[v];
                    }
                    theQ.add(v);
                }
            }
            return -1;
        }
    
    
        public static void main(String[] args) {
            int gNodes = 4;
            int[] gFrom = {1, 2, 2, 3};
            int[] gTo = {2, 3, 4, 4};
            int[] gWeights = {2, 1, 2, 3};
            int start =1;
            int end = 4;
            System.out.println(shortestDistance(gNodes, gFrom, gTo, gWeights, start, end));
        }
    }
    

    它没有给出预期的输出,我认为是因为我无法想到如何使用 wExtra 。此外,代码非常混乱。请让我知道错误或随意提供任何功能强大的强大代码。感谢。

1 个答案:

答案 0 :(得分:1)

整合wExtra的可能想法如下:

复制图形,使每个输入节点有两个节点。原始图表示引入新边缘之前的状态。副本代表引入后的状态。对于原始图表中的每个节点n,您应该将权重wExtra的有向边引入副本中的所有节点m,其中m的原始不相邻到n。这基本上表示您可以在任意两个非相邻边之间引入新边。但是一旦你做完了,你就不能回去了。然后,在start与原始endend副本之间的修改后的图表上运行常用的Dijkstra,您应该得到正确的结果。

将图形可视化的最佳方法可能是将两个子图解释为图层。您从原始层开始,并希望到达两个end节点中的一个节点(以较近者为准)。但您可以只切换一次图层。