---
# System prepended metadata

title: 802. Find Eventual Safe States
tags: [Leetcode, medium, python, c++, graph, topological sort]

---

###### tags: `Leetcode` `medium` `graph` `topological sort` `python` `c++`

# 802. Find Eventual Safe States

## [題目連結:] https://leetcode.com/problems/find-eventual-safe-states/description/

## 題目:
There is a directed graph of ```n``` nodes with each node labeled from ```0``` to ```n - 1```. The graph is represented by a **0-indexed** 2D integer array ```graph``` where ```graph[i]``` is an integer array of nodes adjacent to node i, meaning there is an edge from node ```i``` to each node in ```graph[i]```.

A node is a **terminal node** if there are no outgoing edges. A node is a **safe node** if every possible path starting from that node leads to a **terminal node** (or another safe node).

Return an array containing all the **safe nodes** of the graph. The answer should be sorted in **ascending** order.

![](https://i.imgur.com/PBvj0oE.png)


## 解題想法:
* 此題為:
	* terminal node: outdegrees=0的點
	* safe node為，可由此點到達terminal node
* 說明:
	* 此題題目有點複雜，其實簡單而言就是
	* **Step1**: 每次紀錄outdegree=0的node於res
	* **Step2**: 刪除該點，並將其連到此點的邊都刪除
	* loop Step1、Step2 until no more node outdegree=0
* 流程:
	* Step1:建立邊
	```python=
	for pos,val in enumerate(graph):
		for node in val:
			#要反向連
			edges[node].append(pos) #注意!
			outdegrees[pos]+=1 #自己 
			indegrees[node]+=1 #對方
	```
	* ex: graph=[[1,2]], 0->1 and 0->2
		* outdegrees[0]+=1
		* indegrees[1]+=1、indegrees[2]+=1
	* **技巧:** 正常來說應該要是edges[pos].append(pos)
		* **但是為了知道有誰連到terminal**，所以將邊線**反向連**
		* 否則下面進行while時:
		* 若用edges[pos].append(pos)，由於que中的curNode本身就沒連人了，根本檢測不了
	* Step2: que紀錄outdegrees==0的node
	``` python=
	res=[]
	que=[]
	for pos,val in enumerate(outdegrees):
		if val==0:
			que.append(pos)
	```
	* Step3: 刪掉連線，重複尋找
		* 是鄰居的outdegree要-1，因為鄰居連到curNode
	``` python=
	while que:
            curNode=que.pop(0)
            res.append(curNode)
            for neighber in edges[curNode]:
                outdegrees[neighber]-=1
                if outdegrees[neighber]==0:
                    que.append(neighber)
	```
	
	
* 網上看有大神用DFS解題，等二刷再研究ㄌ~
## Python:
``` python=
from collections import defaultdict
class Solution(object):
    def eventualSafeNodes(self, graph):
        """
        :type graph: List[List[int]]
        :rtype: List[int]
        """
        edges=defaultdict(list)
        indegrees=[0]*len(graph)
        outdegrees=[0]*len(graph)
        for pos,val in enumerate(graph):
            for node in val:
                #ex: graph=[[1,2]], 0->1 and 0->2
                #正常來說應該是edges[pos].append(pos)
                #但是為了知道有誰連到terminal，所以將邊線反向連
                #否則下面進行while時:
                #若用edges[pos].append(pos)，由於que中的curNode本身就沒連人了，根本檢測不了
                edges[node].append(pos) 
                outdegrees[pos]+=1 #自己 
                indegrees[node]+=1 #對方
        res=[]
        que=[]
        for pos,val in enumerate(outdegrees):
            if val==0:
                que.append(pos)
        while que:
            curNode=que.pop(0)
            res.append(curNode)
            for neighber in edges[curNode]:
                outdegrees[neighber]-=1
                if outdegrees[neighber]==0:
                    que.append(neighber)
        res.sort()
        return res
```

## C++:
``` cpp=
class Solution {
public:
    vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
        unordered_map<int,vector<int>> edges;
        int n=graph.size();
        vector<int> outdegrees(n,0), indegrees(n,0);
        //connect the graph
        for (int i=0; i<n; i++){
            for (auto val: graph[i]){
                edges[val].push_back(i); //反向連
                outdegrees[i]+=1;
                indegrees[val]+=1;
            }
        }
        vector<int> res;
        queue<int> que;
        for (int i=0; i<n; i++){
            if (outdegrees[i]==0)
                que.push(i);
        }
        //collect the node which outdegrees==0
        while (!que.empty()){
            int curNode=que.front(); que.pop();
            res.push_back(curNode);
            for (auto neighber: edges[curNode]){
                outdegrees[neighber]-=1;
                if (outdegrees[neighber]==0)
                    que.push(neighber);
            }
        }
        sort(res.begin(), res.end());
        return res;
    }
};
```