路径枚举必须用dfs,因其能回溯遍历所有分支并天然支持路径暂存与撤销;bfs仅适合最短路径或连通性判断。需用visited防环、邻接表优化存储,递归中维护path和visited,到达终点时保存路径,回退时弹出节点。

路径枚举必须用 DFS,BFS 无法满足“所有路径”需求
因为 BFS 天然按层扩展,只适合找最短路径或判断连通性;而“所有路径”本质是组合爆炸问题,必须回溯遍历所有分支。DFS 借助函数调用栈天然支持路径暂存与撤销,是最直接可行的方案。
注意:图必须是有向或无向的简单图(无自环、无重边),否则需额外去重逻辑;若存在环,必须显式记录已访问节点防止无限递归。
-
std::vector<:vector>></:vector>存储邻接表,比std::map或矩阵更省内存且索引快 - 起点和终点需提前确认存在,否则直接返回空结果
- 路径中允许重复节点?——默认不允许(简单路径),若允许则去掉
visited判断,但可能引发指数级路径数
标准 DFS 实现要带 visited 标记和 path 缓存
核心是递归中维护当前路径 path 和访问状态 visited,到达终点时把 path 拷贝进结果容器;回退前弹出当前节点。
void dfs(int u, int target, const std::vector<:vector>>& graph,
std::vector<bool>& visited, std::vector<int>& path,
std::vector<:vector>>& result) {
path.push_back(u);
if (u == target) {
result.push_back(path);
} else {
for (int v : graph[u]) {
if (!visited[v]) {
visited[v] = true;
dfs(v, target, graph, visited, path, result);
visited[v] = false;
}
}
}
path.pop_back();
}
</:vector></int></bool></:vector>
调用前需初始化:visited[start] = true,path 清空,result 为空容器。
- 传参用引用避免拷贝开销,尤其
path和result - 图用邻接表而非邻接矩阵,稀疏图下空间和遍历效率优势明显
- 若图节点编号不连续(如 ID 是字符串),先做离散化映射到
[0, n)
遇到环或大规模图时必须设路径长度上限
无环图(如 DAG)可安全运行;但一般图中环会导致递归永不终止或结果爆炸。实际使用中几乎总要加保护机制。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 在递归入口加
if (path.size() > MAX_LEN) return;,MAX_LEN根据业务设定(如 15) - 也可用
depth参数替代path.size(),避免每次调用 size() 方法 - 若只需前 K 条路径,可在
result.size() >= K时提前return,配合非 void 返回值或异常中断 - 错误现象:
std::stack_overflow或程序卡死——基本就是没设上限或图含环未标记
C++17 后可用 structured binding 简化路径打印,但别在热路径里用
调试时快速查看结果,可以用:
for (const auto& p : result) {
for (size_t i = 0; i ");
}
}
或者 C++17 写法(更简洁,但生成临时对象):
for (const auto& [a, b, c] : result) { /* 仅当所有路径长度固定为 3 才安全 */ }
这种写法只适用于已知长度的场景;动态长度路径必须用传统循环,否则编译失败或越界访问。
真正复杂的地方不在算法本身,而在你是否预判了图的规模和环的存在——一个没检查的环,能让 dfs 跑满几分钟还不出结果。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










