Finding all the shortest paths between two nodes i

2019-01-08 07:07发布

I need help finding all the shortest paths between two nodes in an unweighted undirected graph.

I am able to find one of the shortest paths using BFS, but so far I am lost as to how I could find and print out all of them.

Any idea of the algorithm / pseudocode I could use?

7条回答
smile是对你的礼貌
2楼-- · 2019-01-08 07:08

@templatetypedef is correct, but he forgot to mention about distance check that must be done before any parent links are added to node. This means that se keep the distance from source in each of nodes and increment by one the distance for children. We must skip this increment and parent addition in case the child was already visited and has the lower distance.

public void addParent(Node n) {
    // forbidding the parent it its level is equal to ours
    if (n.level == level) {
        return;
    }
    parents.add(n);

    level = n.level + 1;
}

The full java implementation can be found by the following link.

http://ideone.com/UluCBb

查看更多
男人必须洒脱
3楼-- · 2019-01-08 07:12

As a caveat, remember that there can be exponentially many shortest paths between two nodes in a graph. Any algorithm for this will potentially take exponential time.

That said, there is a relatively straightforward modification to BFS that you can use as a preprocessing step to speed up generation of all possible paths. Remember that as BFS runs, it proceeds outwards in "layers," getting a single shortest path to all nodes at distance 0, then distance 1, then distance 2, etc. The motivating idea behind BFS is that any node at distance k + 1 from the start node must be connected by an edge to some node at distance k from the start node. BFS discovers this node at distance k + 1 by finding some path of length k to a node at distance k, then extending it by some edge.

If your goal is to find all shortest paths, then you can modify BFS by extending every path to a node at distance k to all the nodes at distance k + 1 that they connect to, rather than picking a single edge. To do this, modify BFS in the following way: whenever you process an edge by adding its endpoint in the processing queue, don't immediately mark that node as being done. Instead, insert that node into the queue annotated with which edge you followed to get to it. This will potentially let you insert the same node into the queue multiple times if there are multiple nodes that link to it. When you remove a node from the queue, then you mark it as being done and never insert it into the queue again. Similarly, rather than storing a single parent pointer, you'll store multiple parent pointers, one for each node that linked into that node.

If you do this modified BFS, you will end up with a DAG where every node will either be the start node and have no outgoing edges, or will be at distance k + 1 from the start node and will have a pointer to each node of distance k that it is connected to. From there, you can reconstruct all shortest paths from some node to the start node by listing of all possible paths from your node of choice back to the start node within the DAG. This can be done recursively:

  • There is only one path from the start node to itself, namely the empty path.
  • For any other node, the paths can be found by following each outgoing edge, then recursively extending those paths to yield a path back to the start node.

Hope this helps!

查看更多
Ridiculous、
4楼-- · 2019-01-08 07:17

templatetypedef your answer was very good, thank you a lot for that one(!!), but it missed out one point:

If you have a graph like this:

A-B-C-E-F
  |     |
  D------

Now lets imagine I want this path:

A -> E.

It will expand like this:

 A-> B -> D-> C -> F -> E.

The problem there is, that you will have F as a parent of E, but

 A->B->D->F-E 
is longer than

 A->B->C->E.
You will have to take of tracking the distances of parents you are so happily adding.

查看更多
forever°为你锁心
5楼-- · 2019-01-08 07:20

First, find the distance-to-start of all nodes using breadth-first search.

(if there are a lot of nodes, you can use A* and stop when top of the queue has distance-to-start > distance-to-start(end-node). This will give you all nodes that belong to some shortest path)

Then just backtrack from the end-node. Anytime a node is connected to two (or more) nodes with a lower distance-to-start, you branch off into two (or more) paths.

查看更多
该账号已被封号
6楼-- · 2019-01-08 07:21

BFS stops when you find what you want.

You have to modify the algorithm so it continues its execution when the first path is found. (delete the return statement and save the path somehow.

You may end the execution after check the last node of the level that has the ending nodes of the shortest paths. (All ending nodes of the shortest paths are at the same level)


Also, there known algorithm that find all shortest paths:

Floyd–Warshall algorithm (it has pseudocode)

Johnson's algorithm

查看更多
太酷不给撩
7楼-- · 2019-01-08 07:27

Step 1: Traverse the graph from the source by BFS and assign each node the minimal distance from the source

Step 2: The distance assigned to the target node is the shortest length

Step 3: From source, do a DFS search along all paths where the minimal distance is increased one by one until the target node is reached or the shortest length is reached. Print the path whenever the target node is reached.

查看更多
登录 后发表回答