【代码随想录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]);
    }
}
相关推荐
从琳开始98914 分钟前
从Socket到TCP回显服务器:Java网络编程完整指南
java·服务器·网络·tcp/ip·java-ee
养军博客15 分钟前
Spring Security 4.x / 5.x / 6.x 配置全对比:前后端不分离与前后端分离
java·后端·spring·springsecurity
wifi___16 分钟前
SpringBoot自动装配原理
java·spring boot·后端
SL_staff1 小时前
制造订单交付闭环实践:用跨部门计划模板解决缺料-停机-返工三角死循环
java·开源·产品
device_Any1 小时前
接口文档写着三个字段,接口返回了五个
android·java·linux
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 小视频模块实战:访客记录、FastDFS 存储与 SpringCache 缓存
java·缓存·交友
BuHuaX1 小时前
Lua 与 ToLua:运行机制及热更新原理
开发语言·unity·junit·c#·lua
xys_6781 小时前
深挖C++:C++入门基础
开发语言·c++
香蕉大香蕉(06敬畏市场)1 小时前
MySQL 单点详解(09)
java·数据库·mysql·面试·八股·大厂实习