leetcode 207. 课程表 (拓扑排序)

题目描述:

题目链接: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 。这是可能的。

示例 2:

输入:numCourses = 2, prerequisites = [[1,0],[0,1]]
输出:false
解释:总共有 2 门课程。学习课程 1 之前,你需要先完成​课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。

提示:

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

分析

经典拓扑排序模型。只要课程和课程间构成的有向图不存在环,则课程的安排是合理的。故此题用拓扑排序判断一下是否存在环即可。

C++ 代码

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        int n=prerequisites.size();
        if(numCourses==1||n==0) return true; //只有一门课或者图为空则不存在环
        vector<int>in(numCourses,0);   //记录入度
        vector<vector<int>>Graph(numCourses,vector<int>()); //存图
        for(int i=0;i<n;i++)
        {
            int u=prerequisites[i][1];
            int v=prerequisites[i][0];
            in[v]++;    //记录入度
            Graph[u].push_back(v);  //加边
        }
        int rest=numCourses;   //记录入度不为0的点数
        queue<int>q;
        for(int i=0;i<numCourses;i++)
        {
            if(!in[i])
            {
                q.push(i); 
                rest--;
            }
        }
        
        //bfs"删点"
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=0;i<Graph[u].size();i++)
            {
                int v=Graph[u][i];
                in[v]--;
                if(!in[v])
                {
                    q.push(v);
                    rest--;
                }
            }

        }
        return rest==0;
    }
};

你可能感兴趣的:(算法刷题,leetcode,拓扑排序)