【代码随想录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]);
    }
}
相关推荐
2401_858120531 分钟前
SpringBoot健身房管理:功能与优势分析
java·spring boot·后端
张保瑞2 分钟前
十一:java web(3)-- Spring框架 -- Spring简介
java·前端·spring
coding已疯狂6 分钟前
面试官:说一下SpringBoot 启动流程
java·spring boot·spring
DARLING Zero two♡10 分钟前
关于我、重生到500年前凭借C语言改变世界科技vlog.15——深入理解指针(4)
c语言·开发语言·科技
毕业设计制作和分享10 分钟前
ssm公交车信息管理系统+vue
java·vue.js·spring boot·毕业设计·mybatis
混迹网络的权某11 分钟前
蓝桥杯真题——三角回文数(C语言)
c语言·开发语言·算法·蓝桥杯·改行学it
鸠摩智首席音效师12 分钟前
如何在一个 Docker 容器中运行多个进程 ?
java·docker·容器
PangPiLoLo14 分钟前
高可用架构-业务高可用
java·性能优化·架构
爱上语文17 分钟前
苍穹外卖 商家取消、派送、完成订单
java·开发语言·spring boot·后端
墨柳烟26 分钟前
ABAQUS高亮显示网格节点方法:Python为每个节点建立集合
开发语言·前端·python·abaqus