有向判断是否存在环:
策略:依次寻找图中入度为0的节点,代表这个课没有别的依赖,不需要先修别的课程,然后,将节点踢掉,同时,依赖于它的其他课程入度都-1.
规定:prerequisites中的[i, j]代表i依赖j,j是i的先修,j指向i,而在邻接表中,存在第j行中,也就是说邻接表的第j个元素中保存着j所指向的节点,即j是谁的先修课程,方便将它的children节点入度-1.
using namespace std;
class Solution {
public:
vector<unordered_set<int>> createGraph(int num, vector<vector<int>>& pres){
vector<unordered_set<int>> graph(num);
for(const auto pre: pres){
graph[pre.back()].insert(pre.front());//给定[i, j],i依赖j,j指向i,因此在邻接表的j元素中记录i
}
return graph;
}
vector<int> calcuInDegree(int num, vector<vector<int>>& pres){
vector<int> degrees(num, 0);
for(const auto pre:pres){
degrees[pre.front()]++;
}
return degrees;
}
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<unordered_set<int>> graph = createGraph(numCourses, prerequisites);
vector<int> degrees = calcuInDegree(numCourses, prerequisites);
for(size_t index = 0; index < numCourses; ++index){//依次去掉n个点
size_t current = 0;//这个位置很好,要是让我做,应该会搞一个flag,循环中退出前修改flag,依据flag判断退出原因,但是这里更巧妙。
for(; current < numCourses; ++current){//寻找入度为0的节点
if(degrees[current] == 0){
break;
}
}
if(current == numCourses)
return false;
else{
degrees[current] -= 1;
for(const auto neighbor : graph[current])
degrees[neighbor]--;
}
}
return true;
}
};
参考:https://blog.csdn.net/qq_26410101/article/details/82759042