题目描述

你这个学期必须选修 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 。这是可能的。
 
链接: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 };