玖雨y的算法刷题记录day11——图论

玖雨y的算法刷题记录day11——图论

  • 题目链接:软件构建
  • 题目思路:本题是拓扑排序的经典题目,什么是拓扑排序呢?给出一个有向图,将这个有向图转为线性排序就叫拓扑排序。大学排课就是拓扑排序的经典应用场景,例如A课是基础课,必须先上完A课,才能上B课,上了B课才能上C课,上了A课才能上D课等等一系列这样的依赖顺序,如何排课就是一种拓扑排序了,分析本题其实也是同类问题。拓扑排序指的是一种解决问题的大体思路,而具体算法可能是广搜也可能是深搜,以下代码采用广搜。首先,根据题目给的示例,我们可以得到这样的文件依赖关系
    在这里插入图片描述
    想必如果给大家这样一张图,大家肯定思路会更加畅通,我们肯定要先处理没有被其他文件指向(即入度为0)的文件,在处理了某个文件后,要将该文件指向的文件的入度减一,所以我们需要维护一个记录入度的数组和一个记录文件关系的列表,具体的代码实现如下。
import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        // 记录入度
        int[] inDegree = new int[n];
        // 记录文件依赖关系
        List<List<Integer>> dependRelation = new ArrayList<>();

        for (int i = 0; i < n; i++) {
            dependRelation.add(new ArrayList<>());
        }

        for (int i = 0; i < m; i++) {
            int s = sc.nextInt();
            int t = sc.nextInt();
            inDegree[t]++;
            // 记录s指向哪些文件,即是哪些文件的前置文件
            dependRelation.get(s).add(t);
        }

        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            if (inDegree[i] == 0) {
                // 入度为0的文件,可以作为开头,先加入队列
                queue.add(i);
            }
        }

        List<Integer> result = new ArrayList<>();

        // 拓扑排序
        while (!queue.isEmpty()) {
            int cur = queue.poll(); // 当前选中的文件
            result.add(cur);
            for (int file : dependRelation.get(cur)) {
                inDegree[file]--; // cur的指向的文件入度-1
                if (inDegree[file] == 0) {
                    queue.add(file);
                }
            }
        }

        // 如果结果集包含的元素个数等于n,说明能成功处理,不然说明存在循环依赖,无法成功处理
        if (result.size() == n) {
            for (int i = 0; i < result.size(); i++) {
                System.out.print(result.get(i));
                if (i < result.size() - 1) {
                    System.out.print(" ");
                }
            }
        } else {
            System.out.println(-1);
        }

    }
}
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值