LeetCode 802. 找到最終的安全狀態
阿新 • • 發佈:2020-10-16
題目描述
在有向圖中, 我們從某個節點和每個轉向處開始, 沿著圖的有向邊走。 如果我們到達的節點是終點 (即它沒有連出的有向邊), 我們停止。
現在, 如果我們最後能走到終點,那麼我們的起始節點是最終安全的。 更具體地說, 存在一個自然數 \(K\), 無論選擇從哪裡開始行走, 我們走了不到 \(K\) 步後必能停止在一個終點。
哪些節點最終是安全的? 結果返回一個有序的陣列。
該有向圖有 N
個節點,標籤為 0, 1, ..., N-1
, 其中 N
是graph
的節點數. 圖以以下的形式給出: graph[i]
是節點 j
的一個列表,滿足 (i, j)
是圖的一條有向邊。
示例:
輸入:graph = [[1,2],[2,3],[5],[0],[5],[],[]] 輸出:[2,4,5,6]
這裡是上圖的示意圖。
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/find-eventual-safe-states
思路解析
- 定義安全節點:
沒有出邊的節點均為安全節點;
出邊連線的節點均為安全節點的節點。 - 查詢圖的最終安全節點(沒有出邊的節點)
- 將圖反向,得到
rGraph
,依次查詢僅與安全節點相連的節點,並存入佇列
程式碼實現
class Solution { public: vector<int> eventualSafeNodes(vector<vector<int>>& graph) { // Find terminate vector<int> terminates; vector<int> degree; for(int i = 0; i < graph.size(); i++) { if(graph[i].empty()) terminates.push_back(i); degree.push_back(graph[i].size()); } // Reverse graph vector<vector<int>> rGraph = reverseGraph(graph); // Construct queue queue<int> safeNodes; for(auto node : terminates) safeNodes.push(node); while(!safeNodes.empty()) { int curNode = safeNodes.front(); for(auto pNode : rGraph[curNode]) { for(auto tNode : graph[pNode]) { if(tNode == curNode) { degree[pNode]--; break; } } if(degree[pNode] <= 0) { safeNodes.push(pNode); terminates.push_back(pNode); } /* for(auto nt = graph[pNode].begin(); nt != graph[pNode].end(); nt++) { if((*nt) == curNode) graph[pNode].erase(nt); if(nt == graph[pNode].end()) break; } if(graph[pNode].empty()) { safeNodes.push(pNode); terminates.push_back(pNode); } */ } safeNodes.pop(); } sort(terminates.begin(), terminates.end()); return terminates; } vector<vector<int>> reverseGraph(vector<vector<int>> graph) { vector<vector<int>> rGraph(graph.size(), vector<int>{}); for(int i = 0; i < graph.size(); i++) for(auto tNode : graph[i]) rGraph[tNode].push_back(i); return rGraph; } };