leetcode链接:
一、题目描述:
你这个学期必须选修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。这是可能的。
提示:
1 <= numCourses <= 2000
0 <= prerequisites.length <= 5000
prerequisites[i].length == 2
0 <= ai, bi < numCourses
prerequisites[i]
中的所有课程对 互不相同
二、思路:
考虑拓扑排序中最前面的节点,该节点一定没有任何入边,即没有任何的先修课程要求;
当将一个节点加入答案后,就可以移除它的所有出边,代表着它的相邻节点少了一门先修课程的要求;
如果某个相邻节点变成没有任何入边的节点,那么就代表这门课可以开始学习了;
按照这种流程,不断将没有入边的节点加入答案,直到答案中包含所有的节点【拓扑排序】或者不存在没有入边的节点【有环】。
三、代码:
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
edges.resize(numCourses);
indeg.resize(numCourses);
for(auto info : prerequisites) {
edges[info[1]].push_back(info[0]);
++indeg[info[0]];
}
queue<int> q;
for(int i=0;i<numCourses;++i) {
if(indeg[i] == 0) {
q.push(i);//没有入边的节点
}
}
int visited = 0;//按流程最终个数
while(!q.empty()) {
++visited;
int u = q.front();
q.pop();
for(int v : edges[u]) {
--indeg[v];
if(indeg[v] == 0) {//产生没有入边的节点
q.push(v);
}
}
}
return visited == numCourses;
}
private:
vector<vector<int>> edges;
vector<int> indeg;
};
四、题目拓展:
小米手机的生产制造过程依赖复杂的焊接,集成,封装,测试等流程,工序之间存在相互依赖,假设必须完成的 n 门工序,记为0到n-1,在完成某些工序之前需要先完成前置工序。其中[a:b],表示如果要完成工序a,必须先完成工序b,请你判断工序的编排是否合理,是否可能完成所有工序?如果可以,输出1,否则,输出0.
样例:
输入:2
1:0,0:1
输出:0
注意:ACM模式下,考虑输入格式
#include<bits/stdc++.h>
using namespace std;
int num;
vector<vector<int>> edges;
vector<int> indeg;
int main() {
scanf("%d", &num);
edges.resize(num);
indeg.resize(num);
for(int i=0;i<num;++i) {
int a, b;
scanf("%d:%d", &a, &b); //输入格式处理
edges[b].push_back(a);
++indeg[a];
if(i < num-1) getchar(); //,
}
queue<int> q;
for(int i=0;i<num;++i) {
if(indeg[i] == 0) {
q.push(i);
}
}
int visited = 0;
while(!q.empty()) {
++visited;
int u = q.front();
q.pop();
for(int v : edges[u]) {
--indeg[v]
if(indeg[v] == 0) {
q.push(v);
}
}
}
if(visited == num) {
cout << "1" << endl; //输出
} else {
cout << "0" << endl;
}
return 0;
}