使用Dijkstra检测多条最短路径

时间:2018-05-18 13:04:29

标签: java graph-theory shortest-path dijkstra

给定加权有向图,如何修改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 ) );
            }
        }
    }
}

2 个答案:

答案 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'。如果PP'包含相同的边,那么您可以得出结论:P是唯一的最短路径。否则,我们撤消epsilon更改并比较PP'的长度。如果长度相等,那么显然P'是另一条截然不同的最短路径。否则,P是唯一的最短路径。

如果我们想找到所有最短路径

这种算法必然是指数时间。这是因为图形可以在两个节点之间具有指数级的许多等成本路径。例如,考虑图表:

A --> B1 --> C --> D1 --> E ...
  \       ->   \       ->
   -> B2 /      -> D2 /

AE有4条路径,如果我们假设所有边都是相等的费用,则所有这些路径的总费用相等。通过重复这种模式,我们可以指数级地获得相同成本的许多路径。