【代码随想录Day57】图论Part08

拓扑排序精讲

题目链接/文章讲解:代码随想录

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

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取文件数量 n 和依赖关系数量 m
        int n = scanner.nextInt();
        int m = scanner.nextInt();

        // 初始化记录文件依赖关系的列表和每个文件的入度数组
        List<List<Integer>> umap = new ArrayList<>(n); // 记录文件依赖关系
        int[] inDegree = new int[n]; // 记录每个文件的入度

        // 初始化 umap,每个文件的依赖列表
        for (int i = 0; i < n; i++) {
            umap.add(new ArrayList<>());
        }

        // 读取依赖关系
        for (int i = 0; i < m; i++) {
            int s = scanner.nextInt(); // 依赖的源文件
            int t = scanner.nextInt(); // 依赖的目标文件
            umap.get(s).add(t); // 记录s指向哪些文件
            inDegree[t]++; // t的入度加一,表示有一个文件依赖于t
        }

        // 使用 ArrayDeque 作为队列来进行拓扑排序
        Deque<Integer> queue = new ArrayDeque<>();

        // 将所有入度为0的文件加入队列
        for (int i = 0; i < n; i++) {
            if (inDegree[i] == 0) {
                queue.add(i); // 入度为0的文件可以作为开头
            }
        }

        // 存储拓扑排序结果
        List<Integer> result = new ArrayList<>();

        // 拓扑排序过程
        while (!queue.isEmpty()) {
            int cur = queue.poll(); // 当前选中的文件
            result.add(cur); // 将当前文件加入结果列表

            // 遍历当前文件指向的所有文件
            for (int file : umap.get(cur)) {
                inDegree[file]--; // 当前文件指向的文件入度-1
                if (inDegree[file] == 0) {
                    queue.add(file); // 如果入度为0,则加入队列
                }
            }
        }

        // 检查是否完成了拓扑排序
        if (result.size() == n) {
            // 如果结果列表的大小等于文件数量,说明拓扑排序成功
            StringBuilder output = new StringBuilder();
            for (int i = 0; i < result.size(); i++) {
                output.append(result.get(i)); // 添加文件到输出
                if (i < result.size() - 1) {
                    output.append(" "); // 添加空格分隔文件
                }
            }
            System.out.println(output); // 输出最终结果
        } else {
            // 如果结果列表的大小不等于文件数量,说明存在循环依赖
            System.out.println(-1);
        }
    }
}

dijkstra(朴素版)精讲

题目链接/文章讲解:代码随想录

java 复制代码
import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取节点数量 n 和边的数量 m
        int n = scanner.nextInt();
        int m = scanner.nextInt();

        // 初始化图的邻接矩阵,使用 Integer.MAX_VALUE 表示无穷大
        int[][] grid = new int[n + 1][n + 1];
        for (int i = 1; i <= n; i++) {
            Arrays.fill(grid[i], Integer.MAX_VALUE);
        }

        // 读取边的信息,建立邻接矩阵
        for (int i = 0; i < m; i++) {
            int p1 = scanner.nextInt();
            int p2 = scanner.nextInt();
            int val = scanner.nextInt();
            // 存储边的权值,假设图是有向图
            grid[p1][p2] = Math.min(grid[p1][p2], val); // 保证边的权值最小
        }

        int start = 1; // 起始点
        int end = n;   // 终点

        // 存储从起始点到每个节点的最短距离
        int[] minDist = new int[n + 1];
        Arrays.fill(minDist, Integer.MAX_VALUE);
        minDist[start] = 0; // 起始点到自身的距离为0

        // 记录每个节点是否被访问过
        boolean[] visited = new boolean[n + 1];

        // Dijkstra 算法主循环
        for (int i = 1; i <= n; i++) {
            // 1. 找到未访问的节点中最小距离的节点
            int cur = -1;
            int minVal = Integer.MAX_VALUE;

            for (int v = 1; v <= n; ++v) {
                if (!visited[v] && minDist[v] < minVal) {
                    minVal = minDist[v];
                    cur = v; // 记录当前节点
                }
            }

            // 如果所有节点都已访问,或剩下的节点不可达,则退出循环
            if (cur == -1) break;

            visited[cur] = true; // 2. 标记当前节点已被访问

            // 3. 更新未访问节点到起始点的距离
            for (int v = 1; v <= n; v++) {
                // 如果有边且未访问,更新最短距离
                if (!visited[v] && grid[cur][v] != Integer.MAX_VALUE) {
                    minDist[v] = Math.min(minDist[v], minDist[cur] + grid[cur][v]);
                }
            }
        }

        // 输出结果
        System.out.println(minDist[end] == Integer.MAX_VALUE ? -1 : minDist[end]);
    }
}
相关推荐
超级大只老咪4 小时前
数组相邻元素比较的循环条件(Java竞赛考点)
java
hh随便起个名4 小时前
力扣二叉树的三种遍历
javascript·数据结构·算法·leetcode
小浣熊熊熊熊熊熊熊丶4 小时前
《Effective Java》第25条:限制源文件为单个顶级类
java·开发语言·effective java
毕设源码-钟学长4 小时前
【开题答辩全过程】以 公交管理系统为例,包含答辩的问题和答案
java·eclipse
啃火龙果的兔子4 小时前
JDK 安装配置
java·开发语言
星哥说事4 小时前
应用程序监控:Java 与 Web 应用的实践
java·开发语言
派大鑫wink4 小时前
【JAVA学习日志】SpringBoot 参数配置:从基础到实战,解锁灵活配置新姿势
java·spring boot·后端
xUxIAOrUIII5 小时前
【Spring Boot】控制器Controller方法
java·spring boot·后端
Dolphin_Home5 小时前
从理论到实战:图结构在仓库关联业务中的落地(小白→中级,附完整代码)
java·spring boot·后端·spring cloud·database·广度优先·图搜索算法
等....5 小时前
Miniconda使用
开发语言·python