题目描述
你这个学期必须选修 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 。这是可能的。
输出:true
解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
链接:https://leetcode-cn.com/problems/course-schedule
分析思路
使用拓扑排序、广度优先遍历求解此题,首先生成每个节点的入度表,然后借助一个队列将入度为0的顶点入队,并依次出队,同时将其所有的邻接顶点入度减1,如果邻接顶点的入度变为1,则将该顶点入队,并重复上述操作。
代码实现
1 class Solution { 2 public: 3 bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { 4 vector<int> v; 5 //生成入度表 6 vector<int> indegree(numCourses, 0); 7 //构建临接表 8 vector<vector<int>> graph(numCourses, v); 9 //构建入度为0的队列 10 queue<int> myque; 11 for(int i = 0; i < prerequisites.size(); i ++){ 12 int pre = prerequisites[i][1]; 13 int later = prerequisites[i][0]; 14 indegree[later] ++; 15 //将pre->later保存下来 16 graph[pre].push_back(later); 17 } 18 //将入度为0的顶点入队 19 for(int i = 0; i < numCourses; i ++){ 20 if(indegree[i] == 0){ 21 myque.push(i); 22 } 23 } 24 int count = 0; 25 //队列是否为空,并继续将入度为0的顶点入队 26 while(!myque.empty()){ 27 int pre = myque.front(); 28 myque.pop(); 29 count++; 30 //更新入度表 31 for(int i = 0; i < graph[pre].size(); i ++){ 32 int later = graph[pre][i]; 33 indegree[later] --; 34 //如果入度减为0,则将该顶点入列 35 if(indegree[later] == 0) 36 myque.push(later); 37 } 38 } 39 return count == numCourses; 40 } 41 };