###### 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; } }; ```