• 拓扑排序模板【广度优先搜索】


    leetcode链接:

    207. 课程表

    一、题目描述:

            你这个学期必须选修numCourses门课程,记为0到numCourses-1。

            在选修某些课程之前需要一些先修课程。先修课程按数组prerequisites给出,其中prerequisites[i] = [ai, bi],表示如果学习课程ai则必须先学习课程bi。

            例如,先修课程对[0,1]表示:想要学习课程0,你需要先完成课程1。

            请你判断是否可能完成所有课程的学习?如果可以,返回true;否则,返回false。

            示例1:

                    输入:numCourses=2,prerequisites=[[1,0]]

                    输出:true

                    解释:总共有2门课程。学习课程1之前,你需要完成课程0。这是可能的。

    提示:

    • 1 <= numCourses <= 2000
    • 0 <= prerequisites.length <= 5000
    • prerequisites[i].length == 2
    • 0 <= ai, bi < numCourses
    • prerequisites[i] 中的所有课程对 互不相同

    二、思路:

            考虑拓扑排序中最前面的节点,该节点一定没有任何入边,即没有任何的先修课程要求;

            当将一个节点加入答案后,就可以移除它的所有出边,代表着它的相邻节点少了一门先修课程的要求;

            如果某个相邻节点变成没有任何入边的节点,那么就代表这门课可以开始学习了;

            按照这种流程,不断将没有入边的节点加入答案,直到答案中包含所有的节点【拓扑排序】或者不存在没有入边的节点【有环】。

    三、代码:

    1. class Solution {
    2. public:
    3. bool canFinish(int numCourses, vectorint>>& prerequisites) {
    4. edges.resize(numCourses);
    5. indeg.resize(numCourses);
    6. for(auto info : prerequisites) {
    7. edges[info[1]].push_back(info[0]);
    8. ++indeg[info[0]];
    9. }
    10. queue<int> q;
    11. for(int i=0;i
    12. if(indeg[i] == 0) {
    13. q.push(i);//没有入边的节点
    14. }
    15. }
    16. int visited = 0;//按流程最终个数
    17. while(!q.empty()) {
    18. ++visited;
    19. int u = q.front();
    20. q.pop();
    21. for(int v : edges[u]) {
    22. --indeg[v];
    23. if(indeg[v] == 0) {//产生没有入边的节点
    24. q.push(v);
    25. }
    26. }
    27. }
    28. return visited == numCourses;
    29. }
    30. private:
    31. vectorint>> edges;
    32. vector<int> indeg;
    33. };

    四、题目拓展:

            小米手机的生产制造过程依赖复杂的焊接,集成,封装,测试等流程,工序之间存在相互依赖,假设必须完成的 n 门工序,记为0到n-1,在完成某些工序之前需要先完成前置工序。其中[a:b],表示如果要完成工序a,必须先完成工序b,请你判断工序的编排是否合理,是否可能完成所有工序?如果可以,输出1,否则,输出0.

            样例:

                    输入:2

                               1:0,0:1

                    输出:0

    注意:ACM模式下,考虑输入格式

    1. #include
    2. using namespace std;
    3. int num;
    4. vectorint>> edges;
    5. vector<int> indeg;
    6. int main() {
    7. scanf("%d", &num);
    8. edges.resize(num);
    9. indeg.resize(num);
    10. for(int i=0;i
    11. int a, b;
    12. scanf("%d:%d", &a, &b); //输入格式处理
    13. edges[b].push_back(a);
    14. ++indeg[a];
    15. if(i < num-1) getchar(); //,
    16. }
    17. queue<int> q;
    18. for(int i=0;i
    19. if(indeg[i] == 0) {
    20. q.push(i);
    21. }
    22. }
    23. int visited = 0;
    24. while(!q.empty()) {
    25. ++visited;
    26. int u = q.front();
    27. q.pop();
    28. for(int v : edges[u]) {
    29. --indeg[v]
    30. if(indeg[v] == 0) {
    31. q.push(v);
    32. }
    33. }
    34. }
    35. if(visited == num) {
    36. cout << "1" << endl; //输出
    37. } else {
    38. cout << "0" << endl;
    39. }
    40. return 0;
    41. }
  • 相关阅读:
    Apache DolphinScheduler新一代分布式工作流任务调度平台实战-上
    企业级邮件系统架构
    MySQL安全问题
    《动手学深度学习 Pytorch版》 8.4 循环神经网络
    【.NET Core】创建一个在后台运行的控制台程序(ConsoleApp)
    七甲川染料CY7标记PLGA纳米粒|CY7-PLGA|PLGA-CY7|CY7-Se-PEG-PLGA
    Qt鼠标事件全面解析:从基础到实战
    基于Java毕业设计服务管理系统源码+系统+mysql+lw文档+部署软件
    全网最牛自动化测试框架系列之pytest(9)-标记用例(指定执行、跳过用例、预期失败)
    从 IPv4 向 IPv6 的迁移
  • 原文地址:https://blog.csdn.net/xiaoyeren_ITRoad/article/details/133778365