Leetcode 802 找到最终的安全状态(拓扑)
题目描述:
在有向图中, 我们从某个节点和每个转向处开始, 沿着图的有向边走。 如果我们到达的节点是终点 (即它没有连出的有向边), 我们停止。现在, 如果我们最后能走到终点,那么我们的起始节点是最终安全的。 更具体地说, 存在一个自然数 K, 无论选择从哪里开始行走, 我们走了不到 K 步后必能停止在一个终点。哪些节点最终是安全的? 结果返回一个有序的数组。该有向图有 N 个节点,标签为 0, 1, ..., N-1, 其中 N 是 graph 的节点数. 图以以下的形式给出: graph[i] 是节点 j 的一个列表,满足 (i, j) 是图的一条有向边。
题解:
根据题意分析,出度为0的点为最终安全点,一个点能够到达的点都是最终安全点的话,这个点也是安全点。那么对于这个有向图,我们反向建图,那么入度为0的点就是最终安全点,按照拓扑排序的思路依次处理下去,剩下的点就是不安全的点了。
AC代码:
class Solution { public: // vector<int> Topo(int n,vector<vector<int>>& edge) { queue<int> que; vector<int> res; int vis[n+1]; memset(vis,0,sizeof(vis)); for(int i=0;i<n;i++) { if(degree[i] == 0) { que.push(i); vis[i] = 1; } } while(!que.empty()) { int now = que.front(); que.pop(); for(auto & next:edge[now]) { degree[next]--; if(degree[next] == 0 && vis[next] == 0) { que.push(next); vis[next] = 1; } } } for(int i=0;i<n;i++) { if(vis[i] == 1) res.push_back(i); } return res; } vector<int> eventualSafeNodes(vector<vector<int>>& graph) { int n = graph.size(); if(n == 0) return {}; vector<vector<int> > edge(n); memset(degree,0,sizeof(degree)); for(int i=0;i<n;i++) { for(auto &next:graph[i]) { edge[next].push_back(i); degree[i]++; } } vector<int> ans = Topo(n,edge); return ans; } private: int degree[10010]; };