你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]
给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?
示例 1:
输入: 2, [[1,0]]
输出: true
解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。
示例 2:
输入: 2, [[1,0],[0,1]]
输出: false
解释: 总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0;并且学习课程 0 之前,你还应先完成课程 1。这是不可能的。
提示:
输入的先决条件是由 边缘列表 表示的图形,而不是 邻接矩阵 。详情请参见图的表示法。
你可以假定输入的先决条件中没有重复的边。
1 <= numCourses <= 10^5
code1:邻接表+bfs;
从给定的二维数组构造形如a->b邻接表,并计算以b为后继的结点的入度,遍历所有课程,找出入度为0的课程,加入队列
- 遍历队列找出入度为0的点,
- 把邻接表中以此点为前驱的所有结点的入度都减一,如果发现入度为0的点,加入队列
- 直到队列为空,否则重复1-2
class Solution { public: bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { map<int,set<int>> adjcent;//邻接表 vector<int> indegree(numCourses);//以i为顶点的入度 for(const auto& edg:prerequisites) { adjcent[edg[1]].insert(edg[0]); ++indegree[edg[0]]; } //入度为0的顶点入队列 queue<int> indegreeZero; for(int i=0;i<numCourses;++i) { if(!indegree[i]) indegreeZero.push(i); } int count=0; while(!indegreeZero.empty()) { int v=indegreeZero.front(); indegreeZero.pop(); ++count; auto adj=adjcent[v]; for(auto i:adj) { --indegree[i];//以i为前驱的结点的入度减一 if(!indegree[i]) indegreeZero.push(i); } } return count==numCourses; } };
code:dfs,每个结点有个访问标记flag;
- 如果该结点没有被访问过,flag==0
- 如果结点点被其他结点启动的dfs访问过,flag==-1
- 如果该结点被当前节点启动的dfs访问过,flag==1
以每个课程为起点,dfs邻接表,判断每个结点起步的dfs是否存在环,若存在返回false,对该结点的邻接点进行dfs
- 如果flag==-1,说明被其他结点访问过无需再次遍历,返回true,如果flag==1,说明在此次dfs中2次来到该结点,则存在环,返回false
- 将当前访问结点的flag置为1
- 对以该结点起步的所有邻接点进行dfs,如果发现换返回false
- 把该节点的flag置为-1
- 若整个图遍历结束未存在环,返回true
class Solution { private: bool dfs(const vector<list<int>>& adjcent,int i,vector<int>& flag) { if(flag[i]==1) return false; if(flag[i]==-1) return true; flag[i]=1; for(const auto& item:adjcent[i]) { if(dfs(adjcent,item,flag)==false) return false; } flag[i]=-1; return true; } public: bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { vector<list<int>> adjcent(numCourses,list<int>()); vector<int> flag(numCourses,0); for(const auto& edg:prerequisites) adjcent[edg[1]].push_back(edg[0]); for(int i=0;i<numCourses;++i) { if(dfs(adjcent,i,flag)==false) return false; } return true; } };