Finding Shortest Path from Source in a 2D graph
Most of the time, we’ll need to find out the shortest path from single source to all other nodes or a specific node in a 2D graph. Say for example: we want to find out how many moves are required for a knight to reach a certain square in a chessboard, or we have an array where some cells are blocked, we have to find out the shortest path from one cell to another. We can move only horizontally and vertically. Even diagonal moves can be possible too. For these cases, we can convert the squares or cells in nodes and solve these problems easily using BFS. Now our visited, parent and level will be 2D arrays. For each node, we’ll consider all possible moves. To find the distance to a specific node, we’ll also check whether we have reached our destination.
There will be one additional thing called direction array. This will simply store the all possible combinations of directions we can go to. Let’s say, for horizontal and vertical moves, our direction arrays will be:
+----+-----+-----+-----+-----+ | dx | 1 | -1 | 0 | 0 | +----+-----+-----+-----+-----+ | dy | 0 | 0 | 1 | -1 | +----+-----+-----+-----+-----+
Here dx represents move in x-axis and dy represents move in y-axis. Again this part is optional. You can also write all the possible combinations separately. But it’s easier to handle it using direction array. There can be more and even different combinations for diagonal moves or knight moves.
The additional part we need to keep in mind is:
- If any of the cell is blocked, for every possible moves, we’ll check if the cell is blocked or not.
- We’ll also check if we have gone out of bounds, that is we’ve crossed the array boundaries.
- The number of rows and columns will be given.
Our pseudo-code will be:
Procedure BFS2D(Graph, blocksign, row, column): for i from 1 to row for j from 1 to column visited[i][j] := false end for end for visited[source.x][source.y] := true level[source.x][source.y] := 0 Q = queue() Q.push(source) m := dx.size while Q is not empty top := Q.pop for i from 1 to m temp.x := top.x + dx[i] temp.y := top.y + dy[i] if temp is inside the row and column and top doesn't equal to blocksign visited[temp.x][temp.y] := true level[temp.x][temp.y] := level[top.x][top.y] + 1 Q.push(temp) end if end for end while Return level
As we have discussed earlier, BFS only works for unweighted graphs. For weighted graphs, we’ll need Dijkstra’s algorithm. For negative edge cycles, we need Bellman-Ford‘s algorithm. Again this algorithm is single source shortest path algorithm. If we need to find out distance from each nodes to all other nodes, we’ll need Floyd-Warshall’s algorithm.