<p align="center">
<a href="https://www.programmercarl.com/xunlian/xunlianying.html" target="_blank">
  <img src="../pics/训练营.png" width="1000"/>
</a>
<p align="center"><strong><a href="./qita/join.md">参与本项目</a>，贡献其他语言版本的代码，拥抱开源，让更多学习算法的小伙伴们受益！</strong></p>

拓扑排序指的是一种 解决问题的大体思路， 而具体算法，可能是 广搜 可能是深搜。

大家可能发现 各式各样的解法，纠结哪个是拓扑排序？ 

只要能在把 有向无环图 进行线性排序 的算法 都可以叫做 拓扑排序。

引用与任务调度，课程安排等等。


「拓扑排序」是专门应用于有向图的算法；

把一个 有向无环图 转成 线性的排序 就叫 拓扑排序。

拓扑排序（Kahn 算法，其实就是广度优先遍历的思路） 

这道题的做法同样适用于第 210 题。 


```CPP
class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        vector<int> inDegree(numCourses, 0);
        unordered_map<int, vector<int>> umap;
        for (int i = 0; i < prerequisites.size(); i++) {

            // prerequisites[i][0] 是 课程入度，prerequisites[i][1] 是课程出度
            // 即： 上课prerequisites[i][0] 之前，必须先上课prerequisites[i][1]
            // prerequisites[i][1] -> prerequisites[i][0]
            inDegree[prerequisites[i][0]]++;//当前课程入度值+1
            umap[prerequisites[i][1]].push_back(prerequisites[i][0]); // 添加 prerequisites[i][1] 指向的课程
        }
        queue<int> que;
        for (int i = 0; i < numCourses; i++) {
            if (inDegree[i] == 0) que.push(i); // 所有入度为0，即为 开头课程 加入队列
        }
        int count = 0;
        while (que.size()) {
            int cur = que.front();  //当前选的课
            que.pop();
            count++; // 选课数+1
            vector<int> courses = umap[cur]; //获取这门课指向的课程，也就是这么课的后续课
            if (courses.size()) { // 有后续课
                for (int i = 0; i < courses.size(); i++) {
                    inDegree[courses[i]]--; // 它的后续课的入度-1
                    if (inDegree[courses[i]] == 0) que.push(courses[i]); // 如果入度为0，加入队列
                }
            }
        }
        if (count == numCourses) return true;
        return false;

    }
};
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
  <img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>
