How to reconstruct paths from a multi-path Dijkstra?

こ雲淡風輕ζ 提交于 2019-12-02 01:15:26

问题


I am currently writing a PHP library for graphs. I have already implemented a single-path Dijkstra's algorithm successfully, but now struggle with implementing a multi-path version at the path reconstruction stage.

Take following graph:

This graph, for the sake of simplicity, has only paths from vertex A to J, going through multiple other vertices, which are all equal in cost, that is, the edge weight for each path add up to 10. The modified Dijkstra correctly produces the following output (which is the array $this->prev):

Array
(
    [A] => 
    [B] => Array
        (
            [0] => A
        )

    [C] => Array
        (
            [0] => A
        )

    [D] => Array
        (
            [0] => C
        )

    [E] => Array
        (
            [0] => C
        )

    [F] => Array
        (
            [0] => E
            [1] => D
        )

    [G] => Array
        (
            [0] => A
        )

    [H] => Array
        (
            [0] => G
        )

    [I] => Array
        (
            [0] => H
        )

    [J] => Array
        (
            [0] => B
            [1] => F
            [2] => I
        )

)

The current, single-path Dijkstra path reconstruction algorithm is implemented as such:

public function get($dest)
{
    $destReal = $dest;
    $path = array();
    while (isset($this->prev[$dest])) {
        array_unshift($path, $dest);
        $dest = $this->prev[$dest];
    }
    if ($dest === $this->start) {
        array_unshift($path, $dest);
    }

    return array(
        'path' => $path,
        'dist' => $this->dist[$destReal]
    );
}

Is there a way to modify the above, such that it returns me all the paths in a paths array? I have already thought about using maybe a stack or DFS, but couldn't come up with a solution. I also gave foreach loops and recursion a try, to no avail.

What I essentially want to happen is the result to be processed as follows:

  • J connects to B, B connects to A, hence $paths[0] = ['J', 'B', 'A']
  • J connects to F, F connects to E and D, hence continue on through E, remembering to return to F, then create another path through D, resulting in paths[1] = ['J', 'F', 'E', 'C', 'A'] and $paths[2] = ['J', 'F', 'D', 'C', 'A']
  • J connects to I, I connects to H, H connects to G and G connects to A, resulting in $paths[3] = ['J', 'I', 'H', 'G', 'A']

Any help would be appreciated!


回答1:


Like this? (Pseudocode):

function output_paths(source, dest, tail) {

    if source == dest:
        output([dest] + tail)

    for each node in prev[dest]:
        output_paths(source, node, [dest] + tail)
}


output_paths(source=A, dest=J, tail=[])



回答2:


Actually, a modified DFS function I named "enumerate" solved this question. For posterity's sake, here is the code I used to turn the output of the multi-path Dijkstra into an array of paths:

/**
 * Returns all shortest paths to $dest from the origin vertex $this->start in the graph.
 *
 * @param string $dest ID of the destination vertex
 *
 * @return array An array containing the shortest path and distance
 */
public function get($dest)
{
    $this->paths = [];
    $this->enumerate($dest, $this->start);

    return array(
        'paths' => $this->paths,
        'dist' => $this->dist[$dest],
    );
}

/**
 * Enumerates the result of the multi-path Dijkstra as paths.
 *
 * @param string $source ID of the source vertex
 * @param string $dest   ID of the destination vertex
 */
private function enumerate($source, $dest)
{
    array_unshift($this->path, $source);
    $discovered[] = $source;

    if ($source === $dest) {
        $this->paths[] = $this->path;
    } else {
        if (!$this->prev[$source]) {
            return;
        }
        foreach ($this->prev[$source] as $child) {
            if (!in_array($child, $discovered)) {
                $this->enumerate($child, $dest);
            }
        }
    }

    array_shift($this->path);
    if (($key = array_search($source, $discovered)) !== false) {
        unset($discovered[$key]);
    }
}


来源:https://stackoverflow.com/questions/43901833/how-to-reconstruct-paths-from-a-multi-path-dijkstra

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!