# 课程表 II

<p>现在你总共有 <code>numCourses</code> 门课需要选，记为&nbsp;<code>0</code>&nbsp;到&nbsp;<code>numCourses - 1</code>。给你一个数组&nbsp;<code>prerequisites</code> ，其中 <code>prerequisites[i] = [a<sub>i</sub>, b<sub>i</sub>]</code> ，表示在选修课程 <code>a<sub>i</sub></code> 前 <strong>必须</strong> 先选修&nbsp;<code>b<sub>i</sub></code> 。</p>

<ul>
	<li>例如，想要学习课程 <code>0</code> ，你需要先完成课程&nbsp;<code>1</code> ，我们用一个匹配来表示：<code>[0,1]</code> 。</li>
</ul>

<p>返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序，你只要返回 <strong>任意一种</strong> 就可以了。如果不可能完成所有课程，返回 <strong>一个空数组</strong> 。</p>

<p>&nbsp;</p>

<p><strong>示例 1：</strong></p>

<pre>
<strong>输入：</strong>numCourses = 2, prerequisites = [[1,0]]
<strong>输出：</strong>[0,1]
<strong>解释：</strong>总共有 2 门课程。要学习课程 1，你需要先完成课程 0。因此，正确的课程顺序为 <code>[0,1] 。</code>
</pre>

<p><strong>示例 2：</strong></p>

<pre>
<strong>输入：</strong>numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
<strong>输出：</strong>[0,2,1,3]
<strong>解释：</strong>总共有 4 门课程。要学习课程 3，你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。
因此，一个正确的课程顺序是&nbsp;<code>[0,1,2,3]</code> 。另一个正确的排序是&nbsp;<code>[0,2,1,3]</code> 。</pre>

<p><strong>示例 3：</strong></p>

<pre>
<strong>输入：</strong>numCourses = 1, prerequisites = []
<strong>输出：</strong>[0]
</pre>

<p>&nbsp;</p>
<strong>提示：</strong>

<ul>
	<li><code>1 &lt;= numCourses &lt;= 2000</code></li>
	<li><code>0 &lt;= prerequisites.length &lt;= numCourses * (numCourses - 1)</code></li>
	<li><code>prerequisites[i].length == 2</code></li>
	<li><code>0 &lt;= a<sub>i</sub>, b<sub>i</sub> &lt; numCourses</code></li>
	<li><code>a<sub>i</sub> != b<sub>i</sub></code></li>
	<li>所有<code>[a<sub>i</sub>, b<sub>i</sub>]</code> 匹配 <strong>互不相同</strong></li>
</ul>

<p>&nbsp;</p>

<p><strong>拓展：</strong></p>

<ul>
	<li>这个问题相当于查找一个循环是否存在于有向图中。如果存在循环，则不存在拓扑排序，因此不可能选取所有课程进行学习。</li>
	<li><a href="https://www.coursera.org/specializations/algorithms" target="_blank">通过 DFS 进行拓扑排序</a> - 一个关于Coursera的精彩视频教程（21分钟），介绍拓扑排序的基本概念。</li>
	<li>
	<p>拓扑排序也可以通过&nbsp;<a href="https://baike.baidu.com/item/%E5%AE%BD%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2/5224802?fr=aladdin&amp;fromid=2148012&amp;fromtitle=%E5%B9%BF%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2" target="_blank">BFS</a>&nbsp;完成。</p>
	</li>
</ul>

<p>以下错误的选项是？</p>

## aop

### before

```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after

```cpp

```

## 答案

```cpp
class Solution
{
public:
    vector<int> findOrder(int numCourses, vector<pair<int, int>> &prerequisites)
    {
        vector<int> heads(numCourses, -1), degree(numCourses, 0), points, args;
        pair<int, int> p;
        vector<int> ans;
        int from, to, count = 0, len = prerequisites.size();

        for (int i = 0; i < len; ++i)
        {
            p = prerequisites[i];
            from = p.second;
            to = p.first;
            args.push_back(heads[from]);
            points.push_back(to);
            heads[from] = count++;
        }

        queue<int> q;
        for (int i = 0; i < numCourses; ++i)
            if (degree[i] == 0)
            {
                q.push(i);
                ans.push_back(i);
            }
        while (!q.empty())
        {
            from = q.front();
            q.pop();
            to = heads[from];
            while (to != -1)
            {
                if (--degree[points[to]] == 0)
                {
                    q.push(points[to]);
                    ans.push_back(points[to]);
                }
                to = args[to];
            }
        }

        for (int i = 0; i < numCourses; ++i)
            if (degree[i] > 0)
                return vector<int>();

        return ans;
    }
};
```

## 选项


### A

```cpp
class Solution
{
public:
    vector<int> findOrder(int numCourses, vector<vector<int>> &prerequisites)
    {
        int n = numCourses;
        vector<unordered_set<int>> g(n);
        vector<int> m(n);
        for (auto &e : prerequisites)
        {
            int i = e[0], j = e[1];
            g[j].insert(i), m[i]++;
        }
        queue<int> q;
        auto f = [&](int i)
        {
            if (!m[i])
                q.push(i);
        };
        for (int i = 0; i < n; i++)
            f(i);
        vector<int> res;
        while (n--)
        {
            if (q.empty())
                return {};
            int i = q.front();
            q.pop();
            res.push_back(i);
            for (int j : g[i])
                m[j]--, f(j);
        }
        return res;
    }
};
```

### B

```cpp
class Solution
{
private:
    vector<vector<int>> edges;

    vector<int> visited;

    vector<int> result;

    bool invalid;

public:
    void dfs(int u)
    {

        visited[u] = 1;

        for (int v : edges[u])
        {

            if (visited[v] == 0)
            {
                dfs(v);
                if (invalid)
                {
                    return;
                }
            }

            else if (visited[v] == 1)
            {
                invalid = true;
                return;
            }
        }

        visited[u] = 2;

        result.push_back(u);
    }

    vector<int> findOrder(int numCourses, vector<vector<int>> &prerequisites)
    {
        edges.resize(numCourses);
        visited.resize(numCourses);
        for (const auto &info : prerequisites)
        {
            edges[info[1]].push_back(info[0]);
        }

        for (int i = 0; i < numCourses && !invalid; ++i)
        {
            if (!visited[i])
            {
                dfs(i);
            }
        }
        if (invalid)
        {
            return {};
        }

        reverse(result.begin(), result.end());
        return result;
    }
};
```

### C

```cpp
class Solution
{
public:
    vector<int> findOrder(int numCourses, vector<vector<int>> &prerequisites)
    {
        vector<int> result;
        vector<int> fake;
        vector<int> degree(numCourses, 0);
        unordered_map<int, vector<int>> map;
        for (vector<int> prerequisite : prerequisites)
        {
            map[prerequisite[1]].push_back(prerequisite[0]);
            degree[prerequisite[0]]++;
        }
        queue<int> q;
        for (int i = 0; i < numCourses; i++)
        {
            if (degree[i] == 0)
            {
                q.push(i);
            }
        }
        while (!q.empty())
        {
            int cur = q.front();
            result.push_back(cur);
            q.pop();
            for (int next : map[cur])
            {
                degree[next]--;
                if (degree[next] == 0)
                    q.push(next);
            }
        }
        return result.size() == numCourses ? result : fake;
    }
};
```
