1. 问题分析与算法选型
今天我们要解决的是一个经典的图论问题:找出从起点到终点的所有可达路径。这类问题在实际应用中非常常见,比如网络路由规划、社交网络关系分析、游戏地图寻路等场景都会用到。
题目给出了一个有向图,要求我们找出从节点1到节点n的所有路径。输入格式是:第一行两个整数n和m,分别表示节点数和边数;接下来m行每行两个整数s和t,表示一条从s指向t的有向边。
为什么选择深度优先搜索(DFS)加回溯的方法来解决这个问题?主要有以下几个考虑:
-
路径探索特性:DFS天然适合探索所有可能的路径,它会沿着一条路径一直深入,直到无法继续或者到达目标节点,然后回溯尝试其他分支。
-
空间复杂度优势:相比广度优先搜索(BFS),DFS在存储路径时只需要维护当前路径栈,空间复杂度更低。BFS需要存储所有中间状态的路径,在路径数量多时会占用大量内存。
-
实现简洁性:DFS的递归实现非常直观,配合回溯可以清晰地表达"尝试-撤销"的过程,代码可读性强。
注意:在有环图中使用DFS需要特别小心,本题假设图中没有环(虽然题目没有明确说明,但从示例来看是这样),否则需要额外的访问标记来避免无限循环。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据结构设计与实现细节
2.1 图的表示方式
我们选择邻接矩阵来表示图,这是一个n+1×n+1的二维数组(因为节点编号从1开始),其中graph[i][j]为1表示存在从i到j的边。这种表示方式有几个特点:
- 查询效率高:检查两点之间是否有边只需要O(1)时间
- 空间开销大:空间复杂度是O(n²),对于稀疏图来说比较浪费
- 实现简单:特别适合节点数量不是特别大的情况
对于节点数n很大的稀疏图,邻接表会是更好的选择。但在本题的上下文和一般编程竞赛场景中,邻接矩阵通常是首选,因为:
- 题目给定的n通常不会太大(比如n≤100)
- 实现更简单,减少编码错误
- 不需要处理动态数组的内存管理
2.2 核心算法实现
让我们仔细分析DFS函数的实现细节:
cpp复制void dfs(vector<vector<int>>& graph, int index, int n) {
if (index == n) { // 终止条件:到达目标节点
