day48 代码随想录算法训练营 图论专题1

1 今日打卡

深度优先搜索

可达路径 98. 可达路径

广度优先搜索

2 深度优先搜索

代码框架:

3 可达路径

3.1 思路

  1. 数据结构与初始化

邻接矩阵(int [][] graph):用二维数组存储图的边关系,graph[from][to] = 1 表示从from节点到to节点有一条有向边。

全局集合(res):存储所有找到的有效路径(从 1 到 n 的完整路径)。

全局路径(path):记录 DFS 过程中当前正在遍历的路径,通过 "添加 - 递归 - 移除" 的回溯逻辑复用该集合。

  1. DFS 核心逻辑(深度优先搜索 + 回溯)

终止条件:当当前遍历的节点cur等于目标节点des(即节点 n)时,说明找到了一条完整路径,将当前path的副本存入结果集res(必须用new ArrayList<>(path),否则存的是引用,后续回溯会修改结果)。

遍历与递归:对当前节点cur的所有邻接节点(通过邻接矩阵graph[cur][i] == 1判断),执行 3 个操作:

加入路径:将邻接节点i加入path;

递归深入:以i为新的当前节点,继续 DFS;

回溯移除:递归返回后,移除path最后一个节点(恢复现场),尝试其他邻接节点。

  1. 主函数流程

读取输入(节点数 n、边数 m),构建邻接矩阵;

初始化起始路径(将节点 1 加入path,因为路径从 1 开始);

调用 DFS 遍历所有路径;

输出结果:无路径则输出 - 1,有路径则按 "节点 节点 ... 节点" 格式打印每条路径。

3.2 实现代码

java 复制代码
import java.util.*;

public class Main {
    // 存储所有从节点1到节点n的有效路径
    static List<List<Integer>> res = new ArrayList<>();
    // 存储DFS过程中当前遍历的路径(回溯复用)
    static List<Integer> path = new ArrayList<>();

    /**
     * 深度优先搜索(DFS)找所有路径
     * @param graph 邻接矩阵,graph[cur][i]=1表示cur到i有边
     * @param cur 当前遍历的节点
     * @param des 目标节点(即节点n)
     */
    public static void dfs(int[][] graph, int cur, int des) {
        // 终止条件:当前节点到达目标节点,找到一条完整路径
        if (cur == des) {
            // 存入path的副本(避免后续回溯修改结果)
            res.add(new ArrayList<>(path));
            return;
        }

        // 遍历当前节点的所有可能邻接节点(节点编号从1到n)
        for (int i = 1; i < graph.length; i++) {
            // 判断cur到i是否有有向边
            if (graph[cur][i] == 1) {
                path.add(i);          // 将i加入当前路径
                dfs(graph, i, des);   // 递归遍历i的邻接节点
                path.remove(path.size() - 1); // 回溯:移除最后一个节点,尝试其他分支
            }
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 读取节点数n、边数m(节点编号:1~n)
        int n = sc.nextInt(), m = sc.nextInt();
        // 初始化邻接矩阵:n+1行n+1列(避免下标越界,不用0号位置)
        int[][] graph = new int[n+1][n+1];

        // 构建邻接矩阵
        for (int i = 0; i < m; i++) {
            int from = sc.nextInt(); // 边的起点
            int to = sc.nextInt();   // 边的终点
            graph[from][to] = 1;     // 标记有向边
        }

        // 路径从节点1开始,先将1加入path
        path.add(1);
        // 调用DFS:从节点1出发,找到达节点n的所有路径
        dfs(graph, 1, n);

        // 输出结果
        if (res.size() == 0) {
            // 无有效路径时输出-1
            System.out.println(-1);
        } else {
            // 遍历所有有效路径并打印
            for (List<Integer> singlePath : res) {
                // 打印路径的前n-1个节点(带空格)
                for (int i = 0; i < singlePath.size() - 1; i++) {
                    System.out.print(singlePath.get(i) + " ");
                }
                // 打印最后一个节点(换行,避免末尾多余空格)
                System.out.println(singlePath.get(singlePath.size() - 1));
            }
        }
        sc.close(); // 关闭扫描器,释放资源
    }
}

4 广度优先搜索

从start起点开始,是一圈一圈,向外搜索

正是因为BFS一圈一圈的遍历方式,所以一旦遇到终止点,那么一定是一条最短路径。

一圈的待遍历节点,放到容器里保存起来。栈、队列甚至数组都可以。

相关推荐
数模竞赛Paid answer44 分钟前
2025年MathorCup数学建模A题汽车风阻预测解题文档与程序
算法·数学建模·mathorcup
xin_nai1 小时前
LeetCode热题100(Java)(6)矩阵
java·leetcode·矩阵
代码AI弗森6 小时前
一文理清楚“算力申请 / 成本测算 / 并发评估”
java·服务器·数据库
Old Uncle Tom6 小时前
OpenClaw 记忆系统 -- 记忆预加载
java·数据结构·算法·agent
会编程的土豆7 小时前
洛谷题单入门1 顺序结构
数据结构·算法·golang
小小小米粒7 小时前
Collection单列集合、Map(Key - Value)双列集合,多继承实现。
java·开发语言·windows
生信碱移7 小时前
PACells:这个方法可以鉴定疾病/预后相关的重要细胞亚群,作者提供的代码流程可以学习起来了,甚至兼容转录组与 ATAC 两种数据类型!
人工智能·学习·算法·机器学习·数据挖掘·数据分析·r语言
智者知已应修善业7 小时前
【51单片机中的打飞机设计】2023-8-25
c++·经验分享·笔记·算法·51单片机
摇滚侠7 小时前
expdp 查看帮助
java·数据库·oracle
:1218 小时前
java基础
java·开发语言