# 802.找到最终的安全状态 (Medium)

## 问题描述
[802. 找到最终的安全状态 (Medium)](https://leetcode.cn/problems/find-eventual-safe-states/)

有一个有 `n` 个节点的有向图，节点按 `0` 到 `n - 1` 编号。图由一个 **索引从 0 开始** 的 2D
整数数组 `graph` 表示， `graph[i]` 是与节点 `i` 相邻的节点的整数数组，这意味着从节点 `i`
到 `graph[i]` 中的每个节点都有一条边。

如果一个节点没有连出的有向边，则它是 **终端节点**
。如果没有出边，则节点为终端节点。如果从该节点开始的所有可能路径都通向 **终端节点** ，则该节点为 **安全节点**
。

返回一个由图中所有 **安全节点** 组成的数组作为答案。答案数组中的元素应当按 **升序** 排列。

**示例 1：**

![Illustration of
graph](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/03/17/picture1.png)

```
输入：graph = [[1,2],[2,3],[5],[0],[5],[],[]]
输出：[2,4,5,6]
解释：示意图如上。
节点 5 和节点 6 是终端节点，因为它们都没有出边。
从节点 2、4、5 和 6 开始的所有路径都指向节点 5 或 6 。

```

**示例 2：**

```
输入：graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]]
输出：[4]
解释:
只有节点 4 是终端节点，从节点 4 开始的所有路径都通向节点 4 。

```

**提示：**

- `n == graph.length`
- `1 <= n <= 10⁴`
- `0 <= graph[i].length <= n`
- `0 <= graph[i][j] <= n - 1`
- `graph[i]` 按严格递增顺序排列。
- 图中可能包含自环。


## 解题思路
典型的[拓扑排序](https://blog.zwyyy456.tech/zh/posts/tech/topo-sort/)题，但一般的拓扑排序是考虑节点的入度，这里我们需要改为考虑节点的出度，对应的`res`即为所求。

## 代码
```cpp
class Solution {
public:
    vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
        // 拓扑排序，bfs
        int n = graph.size();
        vector<int> in_arr(n);
        for (int i = 0; i < n; ++i) {
            for (int v : graph[i]) {
                in_arr[v]++;
            }
        }
        std::queue<int> in0;
        for (int i = 0; i < n; ++i) {
            // 将入度为0的点放入in0
            if (in_arr[i] == 0) {
                in0.push(i);
            }
        }
        vector<int> res;
        while (!in0.empty()) {
            int idx = in0.front();
            // 从in0中取一个点放入res
            res.push_back(idx);
            in0.pop();
            for (auto v : graph[idx]) {
                if (--in_arr[v] == 0) {
                    in0.push(v);
                }
            }
        }
        return res;
    }
};
```



