给定加权有向图,如何修改Dijkstra算法以测试给定节点对之间存在多个成本最低的路径?
我目前的算法如下:(归功于Weiss)
/**
* Single-source weighted shortest-path algorithm. (Dijkstra)
* using priority queues based on the binary heap
*/
public void dijkstra( String startName )
{
PriorityQueue<Path> pq = new PriorityQueue<Path>( );
Vertex start = vertexMap.get( startName );
if( start == null )
throw new NoSuchElementException( "Start vertex not found" );
clearAll( );
pq.add( new Path( start, 0 ) ); start.dist = 0;
int nodesSeen = 0;
while( !pq.isEmpty( ) && nodesSeen < vertexMap.size( ) )
{
Path vrec = pq.remove( );
Vertex v = vrec.dest;
if( v.scratch != 0 ) // already processed v
continue;
v.scratch = 1;
nodesSeen++;
for( Edge e : v.adj )
{
Vertex w = e.dest;
double cvw = e.cost;
if( cvw < 0 )
throw new GraphException( "Graph has negative edges" );
if( w.dist > v.dist + cvw )
{
w.dist = v.dist +cvw;
w.prev = v;
pq.add( new Path( w, w.dist ) );
}
}
}
}
答案 0 :(得分:1)
将字段prev
替换为前一个顶点与集合prevs
的链接,然后稍微更改代码:
...
if( w.dist >= v.dist + cvw ) {
if ( w.dist > v.dist + cvw ) {
w.dist = v.dist +cvw;
w.prevs.clear();
}
w.prevs.add(v);
pq.add( new Path( w, w.dist ) );
}
...
答案 1 :(得分:0)
假设您已经运行过Dijkstra算法一次以获得最短路径P
。您可以向epsilon
中的每个边缘添加微小的费用P
,然后在修改后的图表上第二次运行Dijkstra,以获得新的路径P'
。如果P
和P'
包含相同的边,那么您可以得出结论:P
是唯一的最短路径。否则,我们撤消epsilon
更改并比较P
和P'
的长度。如果长度相等,那么显然P'
是另一条截然不同的最短路径。否则,P
是唯一的最短路径。
这种算法必然是指数时间。这是因为图形可以在两个节点之间具有指数级的许多等成本路径。例如,考虑图表:
A --> B1 --> C --> D1 --> E ...
\ -> \ ->
-> B2 / -> D2 /
从A
到E
有4条路径,如果我们假设所有边都是相等的费用,则所有这些路径的总费用相等。通过重复这种模式,我们可以指数级地获得相同成本的许多路径。