在看这篇文章之前,我们先要了解图中拓扑排序的基本知识。
(如果不清楚的uu可以先去看一下相关资料:数据结构与算法-图论-拓扑排序)
总而言之,拓扑图(Directed Acyclic Graph简称DAG)是一个有向无环图
其实这两道题类似 都套用一个模版
1.首先需要存储有向图和 存储入度的容器
vector<int> indegree(numCourses);
vector<vector<int>> adjacency(numCourses);
2.然后构造邻接矩阵
for(int i=0;i<prerequisites.size();i++){
indegree[prerequisites[i][0]]++;
adjacency[prerequisites[i][1]].push_back(prerequisites[i][0]);
}
如果不太能够理解,可以代入看看
//indegree[prerequisites[i][0]]++;
[1,0] prerequisites[0][0] = 1
[1,2] prerequisites[1][0] = 1
[2,1] prerequisites[2][0] = 2
indegree中1的入度为2 2的入度为1
//adjacency[prerequisites[i][1]].push_back(prerequisites[i][0]);
把每一对数据中后面的值统一 比如[1,6][2,6][3,2] 6对应1、2 2对应3
3.创建队列 存放入度为0的节点
//队列 存放入度为0的节点
queue<int> zero;
//记录入度为0的值,方便去看拓扑图
for(int i=0;i<numCourses;i++){
if(indegree[i] == 0)
zero.push(i);
}
4.遍历队列 直到zero为0的时候
int count = 0;
while(!zero.empty()){
int visited = zero.front();
count++;
zero.pop();
//拓扑遍历的时候 一学习的course将相关后续课程的入度-1
for(int i=0;i<adjacency[visited].size();i++){
indegree[adjacency[visited][i]]--;
//如果有为0的 则继续加入
if(indegree[adjacency[visited][i]] == 0)
zero.push(adjacency[visited][i]);
}
}
所以课程表I的总体代码如下:
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
if(prerequisites.size() == 0) return true;
//每个顶点的入度
vector<int> indegree(numCourses);
//邻接矩阵
vector<vector<int>> adjacency(numCourses);
//队列 存放入度为0的节点
queue<int> zero;
//构造邻接矩阵
for(int i=0;i<prerequisites.size();i++){
indegree[prerequisites[i][0]]++;
//建立邻接矩阵
adjacency[prerequisites[i][1]].push_back(prerequisites[i][0]);
}
for(int i=0;i<numCourses;i++){
if(indegree[i] == 0)
zero.push(i);
}
int count = 0;
while(!zero.empty()){
int visited = zero.front();
count++;
zero.pop();
for(int i=0;i<adjacency[visited].size();i++){
indegree[adjacency[visited][i]]--;
if(indegree[adjacency[visited][i]] == 0)
zero.push(adjacency[visited][i]);
}
}
return numCourses == count;
}
};
在做第二道题的时候 其实可以偷懒看起来的简洁一点(也有可能是命名问题😌)
class Solution {
public:
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
vector<int> ans;
vector<int> indegree(numCourses,0);
vector<vector<int>> lst(numCourses);
for(auto p:prerequisites){
lst[p[1]].push_back(p[0]);
indegree[p[0]]++;
}
queue<int> q;
for(auto i=0;i<indegree.size();i++){
if(indegree[i] == 0)
q.push(i);
}
while(!q.empty()){
int temp = q.front();
q.pop();
ans.push_back(temp);
for(auto &l : lst[temp]){
--indegree[l];
if(indegree[l] == 0)
q.push(l);
}
}
return (ans.size() == numCourses)? ans: vector<int> ();
}
};
真的是 没有想通之前难得要死 理解之后就豁然开朗。