拓扑排序应用(力扣 课程表I II)

本文介绍了如何使用拓扑排序解决课程安排问题,通过构建邻接矩阵和存储入度,实现从有向无环图中找到有效的课程顺序。文章通过两道相似的题目207.CourseSchedule和210.CourseScheduleII,详细阐述了拓扑排序的步骤,并提供了清晰的代码实现,帮助读者理解拓扑排序在实际问题中的应用。
摘要由CSDN通过智能技术生成

在看这篇文章之前,我们先要了解图中拓扑排序的基本知识。

(如果不清楚的uu可以先去看一下相关资料:数据结构与算法-图论-拓扑排序

总而言之,拓扑图(Directed Acyclic Graph简称DAG)是一个有向无环图

207. Course Schedule

210. Course Schedule II

其实这两道题类似 都套用一个模版

1.首先需要存储有向图和 存储入度的容器

        vector<int> indegree(numCourses);
        vector<vector<int>> adjacency(numCourses);

2.然后构造邻接矩阵

        for(int i=0;i<prerequisites.size();i++){
            indegree[prerequisites[i][0]]++;
            adjacency[prerequisites[i][1]].push_back(prerequisites[i][0]);
        }

如果不太能够理解,可以代入看看

//indegree[prerequisites[i][0]]++;
[1,0]  prerequisites[0][0] = 1
[1,2]  prerequisites[1][0] = 1 
[2,1]  prerequisites[2][0] = 2
indegree中1的入度为2 2的入度为1
//adjacency[prerequisites[i][1]].push_back(prerequisites[i][0]);
把每一对数据中后面的值统一 比如[1,6][2,6][3,2] 6对应1、2 2对应3

3.创建队列 存放入度为0的节点

//队列 存放入度为0的节点
queue<int> zero;
//记录入度为0的值,方便去看拓扑图
for(int i=0;i<numCourses;i++){
    if(indegree[i] == 0)
        zero.push(i);
}

4.遍历队列 直到zero为0的时候

        int count = 0;
        while(!zero.empty()){
            int visited = zero.front();
            count++;
            zero.pop();
            //拓扑遍历的时候 一学习的course将相关后续课程的入度-1
            for(int i=0;i<adjacency[visited].size();i++){
                indegree[adjacency[visited][i]]--;
                //如果有为0的 则继续加入
                if(indegree[adjacency[visited][i]] == 0)
                    zero.push(adjacency[visited][i]);
            }
        }

所以课程表I的总体代码如下:

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        if(prerequisites.size() == 0) return true;
        //每个顶点的入度
        vector<int> indegree(numCourses);
        //邻接矩阵
        vector<vector<int>> adjacency(numCourses);
        //队列 存放入度为0的节点
        queue<int> zero;
        //构造邻接矩阵
        for(int i=0;i<prerequisites.size();i++){
            indegree[prerequisites[i][0]]++;
            //建立邻接矩阵
            adjacency[prerequisites[i][1]].push_back(prerequisites[i][0]);
        }
        for(int i=0;i<numCourses;i++){
            if(indegree[i] == 0)
                zero.push(i);
        }
        int count = 0;
        while(!zero.empty()){
            int visited = zero.front();
            count++;
            zero.pop();
            for(int i=0;i<adjacency[visited].size();i++){
                indegree[adjacency[visited][i]]--;
                if(indegree[adjacency[visited][i]] == 0)
                    zero.push(adjacency[visited][i]);
            }
        }
        return numCourses == count;
    }
};

在做第二道题的时候 其实可以偷懒看起来的简洁一点(也有可能是命名问题😌)

class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        vector<int> ans;
        vector<int> indegree(numCourses,0);
        vector<vector<int>> lst(numCourses);

        for(auto p:prerequisites){
            lst[p[1]].push_back(p[0]);
            indegree[p[0]]++;
        }
        queue<int> q;
        for(auto i=0;i<indegree.size();i++){
            if(indegree[i] == 0)
                q.push(i);
        }
        while(!q.empty()){
            int temp = q.front();
            q.pop();
            ans.push_back(temp);
            for(auto &l : lst[temp]){
                --indegree[l];
                if(indegree[l] == 0)
                    q.push(l);
            }
        }
        return (ans.size() == numCourses)? ans: vector<int> ();
    }
};

真的是 没有想通之前难得要死 理解之后就豁然开朗。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值