📜  门| GATE CS 2021 |设置 2 |第 49 题(1)

📅  最后修改于: 2023-12-03 14:58:21.845000             🧑  作者: Mango

门 | GATE CS 2021 |设置 2 |第 49 题

本题是关于图的遍历的。给出一个有向图,求该图中从起点到终点的所有路径。

题目描述

给定一个由 $n$ 个点和 $m$ 条边构成的有向图,每个点都有一个唯一标识符。请编写一个程序,找出从起点到终点的所有路径。

输入格式

第一行包含两个整数 $n$ 和 $m$,表示点数和边数。接下来 $m$ 行,每行两个整数 $u$ 和 $v$,表示存在一条从 $u$ 到 $v$ 的有向边。

最后一行包含两个整数 $s$ 和 $t$,表示起点和终点的标识符。

输出格式

按照字典序,将所有从起点到终点的路径以如下格式输出:

[起点标识符] -> [中间节点 1 标识符] -> [中间节点 2 标识符] -> ... -> [终点标识符]
举例

输入:

4 6
1 2
1 3
2 3
2 4
3 4
1 4

输出:

1 -> 2 -> 3 -> 4
1 -> 2 -> 4
1 -> 3 -> 4
思路

本题要求从起点到终点的所有路径,因此我们可以使用深度优先搜索(DFS)来遍历图,同时使用一个列表来记录当前已经走过的节点。对于每一个节点,我们将其加入当前已经走过的节点列表中,然后扩展到其能够到达的所有节点。如果找到了终点,就将当前的路径加入结果列表。

最后,我们将结果列表按照字典序排序,并且将每个路径输出即可。

代码
from collections import defaultdict

def all_paths(graph, start, end):
    # 结果列表
    result = []
    # 当前路径列表
    path = [start]
    # 使用 set 来记录已经经过的节点,防止重复经过
    visited = set()
    # 深度优先搜索
    dfs(graph, start, end, path, visited, result)
    # 按照字典序排序并输出
    result.sort()
    return [" -> ".join(map(str, path)) for path in result]

def dfs(graph, node, end, path, visited, result):
    if node == end:
        result.append(list(path))
        return
    for neighbor in graph[node]:
        if neighbor not in visited:
            visited.add(neighbor)
            path.append(neighbor)
            dfs(graph, neighbor, end, path, visited, result)
            visited.remove(neighbor)
            path.pop()

if __name__ == '__main__':
    n, m = map(int, input().split())
    graph = defaultdict(list)
    for i in range(m):
        u, v = map(int, input().split())
        graph[u].append(v)
    start, end = map(int, input().split())
    print("\n".join(all_paths(graph, start, end)))
复杂度分析

本题中使用深度优先搜索来遍历图,时间复杂度为 $O(2^m)$,其中 $m$ 表示边的数量。

由于我们需要遍历所有从起点到终点的路径,并且每条路径需要输出,因此空间复杂度为 $O(2^m)$。注意,这里的空间复杂度不是结果的数量,而是结果路径长度之和。