📜  在无向图中打印给定源和目标之间的所有最短路径

📅  最后修改于: 2021-04-22 07:43:49             🧑  作者: Mango

给定一个无向,不加权的图,并以两个节点作为目标,任务是打印给定源和目标之间最短长度的所有路径。
例子:

方法:要做图形的广度优先遍历(BFS)。步骤如下:

  1. 从源顶点开始BFS遍历。
  2. 在执行BFS时,存储到其他每个节点的最短距离,并且还为每个节点维护父向量。
  3. 将源节点的父节点设为“ -1” 。对于每个节点,它将存储距离源节点最短距离的所有父节点。
  4. 使用父数组恢复所有路径。在任何时候,我们都会在路径数组中推送一个顶点,然后调用其所有父对象。
  5. 如果在上述步骤中遇到“ -1”,则表示已找到路径,并且可以将其存储在paths数组中。

下面是上述方法的实现:

cpp14
// Cpp program for the above approach
#include 
using namespace std;
 
// Function to form edge between
// two vertices src and dest
void add_edge(vector adj[],
              int src, int dest)
{
    adj[src].push_back(dest);
    adj[dest].push_back(src);
}
 
// Function which finds all the paths
// and stores it in paths array
void find_paths(vector >& paths,
                vector& path,
                vector parent[],
                int n, int u)
{
    // Base Case
    if (u == -1) {
        paths.push_back(path);
        return;
    }
 
    // Loop for all the parents
    // of the given vertex
    for (int par : parent[u]) {
 
        // Insert the current
        // vertex in path
        path.push_back(u);
 
        // Recursive call for its parent
        find_paths(paths, path, parent,
                   n, par);
 
        // Remove the current vertex
        path.pop_back();
    }
}
 
// Function which performs bfs
// from the given souce vertex
void bfs(vector adj[],
         vector parent[],
         int n, int start)
{
    // dist will contain shortest distance
    // from start to every other vertex
    vector dist(n, INT_MAX);
 
    queue q;
 
    // Insert source vertex in queue and make
    // its parent -1 and distance 0
    q.push(start);
    parent[start] = { -1 };
    dist[start] = 0;
 
    // Untill Queue is empty
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int v : adj[u]) {
            if (dist[v] > dist[u] + 1) {
 
                // A shorter distance is found
                // So erase all the previous parents
                // and insert new parent u in parent[v]
                dist[v] = dist[u] + 1;
                q.push(v);
                parent[v].clear();
                parent[v].push_back(u);
            }
            else if (dist[v] == dist[u] + 1) {
 
                // Another candidate parent for
                // shortes path found
                parent[v].push_back(u);
            }
        }
    }
}
 
// Function which prints all the paths
// from start to end
void print_paths(vector adj[],
                 int n, int start, int end)
{
    vector > paths;
    vector path;
    vector parent[n];
 
    // Function call to bfs
    bfs(adj, parent, n, start);
 
    // Function call to find_paths
    find_paths(paths, path, parent, n, end);
 
    for (auto v : paths) {
 
        // Since paths contain each
        // path in reverse order,
        // so reverse it
        reverse(v.begin(), v.end());
 
        // Print node for the current path
        for (int u : v)
            cout << u << " ";
        cout << endl;
    }
}
 
// Driver Code
int main()
{
    // Number of vertices
    int n = 6;
 
    // array of vectors is used
    // to store the graph
    // in the form of an adjacency list
    vector adj[n];
 
    // Given Graph
    add_edge(adj, 0, 1);
    add_edge(adj, 0, 2);
    add_edge(adj, 1, 3);
    add_edge(adj, 1, 4);
    add_edge(adj, 2, 3);
    add_edge(adj, 3, 5);
    add_edge(adj, 4, 5);
 
    // Given source and destination
    int src = 0;
    int dest = n - 1;
 
    // Function Call
    print_paths(adj, n, src, dest);
 
    return 0;
}


Python3
# Python program for the above approach
 
# Function to form edge between
# two vertices src and dest
from typing import List
from sys import maxsize
from collections import deque
 
def add_edge(adj: List[List[int]],
             src: int, dest: int) -> None:
    adj[src].append(dest)
    adj[dest].append(src)
 
# Function which finds all the paths
# and stores it in paths array
def find_paths(paths: List[List[int]], path: List[int],
               parent: List[List[int]], n: int, u: int) -> None:
    # Base Case
    if (u == -1):
        paths.append(path.copy())
        return
 
    # Loop for all the parents
    # of the given vertex
    for par in parent[u]:
 
        # Insert the current
        # vertex in path
        path.append(u)
 
        # Recursive call for its parent
        find_paths(paths, path, parent, n, par)
 
        # Remove the current vertex
        path.pop()
 
# Function which performs bfs
# from the given souce vertex
def bfs(adj: List[List[int]],
        parent: List[List[int]], n: int,
        start: int) -> None:
 
    # dist will contain shortest distance
    # from start to every other vertex
    dist = [maxsize for _ in range(n)]
    q = deque()
 
    # Insert source vertex in queue and make
    # its parent -1 and distance 0
    q.append(start)
    parent[start] = [-1]
    dist[start] = 0
 
    # Untill Queue is empty
    while q:
        u = q[0]
        q.popleft()
        for v in adj[u]:
            if (dist[v] > dist[u] + 1):
 
                # A shorter distance is found
                # So erase all the previous parents
                # and insert new parent u in parent[v]
                dist[v] = dist[u] + 1
                q.append(v)
                parent[v].clear()
                parent[v].append(u)
 
            elif (dist[v] == dist[u] + 1):
 
                # Another candidate parent for
                # shortes path found
                parent[v].append(u)
 
# Function which prints all the paths
# from start to end
def print_paths(adj: List[List[int]], n: int,
                start: int, end: int) -> None:
    paths = []
    path = []
    parent = [[] for _ in range(n)]
 
    # Function call to bfs
    bfs(adj, parent, n, start)
 
    # Function call to find_paths
    find_paths(paths, path, parent, n, end)
    for v in paths:
 
        # Since paths contain each
        # path in reverse order,
        # so reverse it
        v = reversed(v)
 
        # Print node for the current path
        for u in v:
            print(u, end = " ")
        print()
 
# Driver Code
if __name__ == "__main__":
 
    # Number of vertices
    n = 6
 
    # array of vectors is used
    # to store the graph
    # in the form of an adjacency list
    adj = [[] for _ in range(n)]
 
    # Given Graph
    add_edge(adj, 0, 1)
    add_edge(adj, 0, 2)
    add_edge(adj, 1, 3)
    add_edge(adj, 1, 4)
    add_edge(adj, 2, 3)
    add_edge(adj, 3, 5)
    add_edge(adj, 4, 5)
 
    # Given source and destination
    src = 0
    dest = n - 1
 
    # Function Call
    print_paths(adj, n, src, dest)
 
# This code is contributed by sanjeev2552


输出:
0 1 3 5 
0 2 3 5 
0 1 4 5

时间复杂度: O(V + E) ,其中V是顶点数,E是边数。
辅助空间: O(V) ,其中V是顶点数。