Dijkstra 算法寻找所有可能的最短路径
我正在研究 Dijkstra 算法,我确实需要找到所有可能的最短路径,而不仅仅是一条。我使用邻接矩阵并应用 Dijkstra 算法,我可以找到最短路径。但我需要找到具有最小成本的所有路径,我的意思是所有可能的解决方案(如果存在)。
对于单一解决方案,这就是我的算法的工作原理:
public void dijkstra( int graph[][] )
{
int d[] = new int[ graph.length ];
int dC[] = new int[ graph.length ];
int p[] = new int[ graph.length ];
for( int i = 0; i < graph.length; i++ ){
d[ i ] = 100; dC[ i ] = 100; p[ i ] = -1;
}
d[ 0 ] = 0; dC[ 0 ] = 0;
int i = 0, min = 200, pos = 0; //You can change the min to 1000 to make it the largest number
while( i < graph.length ){
//extract minimum
for( int j = 0; j < dC.length; j++ ){
if( min > d[ j ] && dC[ j ] != -1 ){
min = d[ j ]; pos = j;
}
}
dC[ pos ] = -1;
//relax
for( int j = 0; j < graph.length; j++ ){
if( d[ j ] > graph[ pos ][ j ] + d[ pos ] ){
d[ j ] = graph[ pos ][ j ] + d[ pos ];
p[ j ] = pos;
}
}
i++; min = 200;
}
for( int j = 0; j < p.length; j++ ){
System.out.print( p[ j ] + " " );
}
System.out.print( "\n" );
for( int j = 0; j < d.length; j++ ){
System.out.print( d[ j ] + " " );
}
System.out.print( "\n" );
}
I'm working on Dijkstra's algorithm, and I really need to find all the possible shortest paths, not just one. I'm using an adjacency matrix and I applied Dijkstra's algorithm, and I can find the shortest path. But I need to find all the paths with that minimum cost, I mean all the possible solutions, if they exist.
This is how my algorithm works, for a single solution:
public void dijkstra( int graph[][] )
{
int d[] = new int[ graph.length ];
int dC[] = new int[ graph.length ];
int p[] = new int[ graph.length ];
for( int i = 0; i < graph.length; i++ ){
d[ i ] = 100; dC[ i ] = 100; p[ i ] = -1;
}
d[ 0 ] = 0; dC[ 0 ] = 0;
int i = 0, min = 200, pos = 0; //You can change the min to 1000 to make it the largest number
while( i < graph.length ){
//extract minimum
for( int j = 0; j < dC.length; j++ ){
if( min > d[ j ] && dC[ j ] != -1 ){
min = d[ j ]; pos = j;
}
}
dC[ pos ] = -1;
//relax
for( int j = 0; j < graph.length; j++ ){
if( d[ j ] > graph[ pos ][ j ] + d[ pos ] ){
d[ j ] = graph[ pos ][ j ] + d[ pos ];
p[ j ] = pos;
}
}
i++; min = 200;
}
for( int j = 0; j < p.length; j++ ){
System.out.print( p[ j ] + " " );
}
System.out.print( "\n" );
for( int j = 0; j < d.length; j++ ){
System.out.print( d[ j ] + " " );
}
System.out.print( "\n" );
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
如果您在这里以伪代码形式查看 Dijkstra 算法:
维基百科 Dijkstra 算法伪代码
您会注意到称为 Relax 的行。目前,它仅包含找到的路径小于当前最短路径的情况,但如果它们相等,则不会执行任何操作。您可能应该将所有同样短的路径保留在列表中。
If you look at Dijkstra's algorithm in pseudocode form here:
Wikipedia Dijkstra's Algorithm Pseudocode
You will notice the line referred to as a Relax. Right now it only contains a case for if the path found is less than the current shortest path, but there isn't anything done if they are equal. You should probably keep all the equally short paths in a List.
如果您的 Dijkstra 算法的实现基于优先级队列,请采用您的第一个解决方案,记录深度并不断弹出解决方案,直到距离发生变化。
If your implementation of Dijkstra's algorithm is based on a priority queue, take your first solution, record the depth and keep popping solutions out until the distance changes.
如果您的图表允许权重 = 0 的边并且还允许循环,请记住有无限多个最短路径,并且您不能希望将它们全部输出!
如果没有零权重边,或者您的图是 DAG,那么您的解决方案仍然存在问题:它要么不会根据需要生成所有最短路径,要么会使用
O(2^N)
空间和时间复杂度。但是,也许可能有尽可能多的最短路径,所以你不能指望在一般情况下做得更好。这是解决稍微更普遍的问题的最佳来源:查找k 最短路径 (Eppstein)。您可以通过迭代最短路径来应用此方法,并在比前一条路径长的第一条路径处停止。
对于仅找到(等效)最短路径的受限问题,Anderson Imes 上面的提示(这是家庭作业吗?否则应该有人拼写出来)很好,并且比上面简单得多。
If your graphs allows edges with
weight = 0
and also allows cycles, bear in mind that there are infinitely many shortest paths, and you cannot hope to output them all!If there are either no zero-weight edges, or your graph is a DAG, then your solution is still problematic: it either doesn't produce all shortest paths as required, or it does so with
O(2^N)
space and time complexity. But then, perhaps there might be as many shortest paths, so you can not hope to do better in the general case.This is the best source for a slightly more general problem: Finding the k Shortest Paths (Eppstein). You could apply this by iterating the shortest paths, stopping at the first path that is longer than the previous.
For the restricted problem of finding only the (equivalent) shortest paths, Anderson Imes' hint above (is this homework? Otherwise someone should spell it out) is good and much simpler than the above.
我不太确定 Dijkstra 算法是否可以轻松适应这一点;当然,这并不像删除访问过的边那么简单,因为n个最短的可能共享其中的一些。
因此,一个近乎蛮力但启发式的解决方案是尝试这个:
我的直觉告诉我它应该可以工作,复杂性的增加与第一个解决方案的长度(边数中的n)成正比......如果没有更多的最短路径,它应该在第一轮结束,如果它找到另一个,它会继续尝试 n-1 次。与原始算法相比,最坏情况下的复杂性增加估计非常糟糕(我猜是n!),但这也意味着有很多路径,所以这是一项需要完成的工作任何算法...
编辑:多思考一下,复杂性的增加可能会比第一个找到的路径的节点数的阶乘更大,因为第二个路径可能有更多的节点!所以我认为估计这种方法的复杂性非常困难,但它应该类似于有效解决方案的数量乘以路径中的平均节点数乘以节点数的平方(最后一个术语是未经修改的算法的原始复杂性)。
编辑2:我找到了一篇关于这个主题的研究论文,需要订阅才能获取全文,但也许你可以在其他地方找到它:http://ieeexplore.ieee.org/Xplore/login.jsp?reload=true&url=http%3A%2F%2Fieeexplore.ieee.org%2Fiel5%2F7719%2F21161%2F00982778.pdf%3Farnumber%3D982778& ;authDecision=-201
I'm not very sure Dijkstra's algorithm can be easily adapted to do that; of course is not as simple as removing the visited edges, because the n shortest might share some of them.
So an almost brute force, but heuristically oriented solution, is to try this:
My intuition tells me that it should work, with an increase in complexity proportional to the length (
n
in number of edges) of the first solution... If there are no more shortest path, it should end in the first round, if it founds another, it goes on withn-1
tries. The worst case complexity increase estimation over the original algorithm is very bad (n!
I guess?), but that also means that there are lots of paths, so that is a work that needs to be done with any algorithm...edit: Thinking a little bit more, the complexity increase might be even larger than the factorial of the number of nodes of the first found path, as the second might have even more nodes! So I think it's very difficult to estimate the complexity of this method, but it should be something like the number of valid solutions times the average number of nodes in the paths times the number of nodes squared (this last term being the original complexity of the unmodified algorithm).
edit 2: I've found a research paper about this subject, it requires subscription to get the full text but maybe you can find it somewhere else: http://ieeexplore.ieee.org/Xplore/login.jsp?reload=true&url=http%3A%2F%2Fieeexplore.ieee.org%2Fiel5%2F7719%2F21161%2F00982778.pdf%3Farnumber%3D982778&authDecision=-201
JgraphT 的 FloydWarshallShortestPaths 类查找所有最短路径。根据上述评论,您正在寻找两个顶点之间的最短路径。您可能需要使用 getShortestPaths 方法,该方法将返回从一个顶点到所有其他顶点的所有最短路径。然后您可能想过滤您感兴趣的结果。
FloydWarshallShortestPaths class of JgraphT finds all shortest paths. Based on above comments, you are looking for shortest paths between two vertices. You may want to use getShortestPaths method, which will return all shortest paths from the a vertex to all other vertices. Then you may want to filter the result which interests you.
考虑这个算法: https://www.programmingalgorithms.com/algorithm/dijkstra's -算法/php/
最后有一个“< $distance[$v])”条件。如果我们将其更改为“<= ...”,它将给出所有现有的最短路径。
为了收集路径,我们可以放置
$this->paths[$v][] = $u;
也排在这里。
整个片段在这里: https://pastebin.com/gk2ymyWw
Consider this algorithm: https://www.programmingalgorithms.com/algorithm/dijkstra's-algorithm/php/
At the end there is a "< $distance[$v])" condition. If we change it to "<= ...", it will give all the existing shortest paths.
For collecting the paths we can put a
$this->paths[$v][] = $u;
row here also.
The whole snippet is here: https://pastebin.com/gk2ymyWw
这篇 1982 年的论文描述了一种用于具有多维边权重的图的算法,给出所有最短路径。
该算法适用于简单的加权图,因此应该适用于您的情况。
作者将其与 Dijkstra 进行了比较,无论是在工作原理上还是在运行时复杂性方面。
用伪代码解释论文:
This paper from 1982 describes an algorithm for graphs with multi-dimensional edge weights, that gives all shortest paths.
The algorithm works fine with simple weighted graphs, so should work for your case.
The author compares it to Dijkstra, both in how it works and in a run-time complexity comparison.
In pseudocode, paraphrasing the paper:
我刚刚解决了一个任务,使用 Dijkstra 算法在 leetcode.com 上找到所有可能的最短路径。
唯一的区别是如何从“parents”和“distances”数组中提取信息。
主要思想是
下面是Python 中的代码。
I Just solved a task to find all possible shortest paths on leetcode.com using Dijkstra's algorithm.
The only difference is how you extract information from "parents" and "distances" arrays.
The main idea is
Below is the code in Python.