每日一题802. 找到最终的安全状态
Posted 7TribeZ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一题802. 找到最终的安全状态相关的知识,希望对你有一定的参考价值。
难度中等241
在有向图中,以某个节点为起始节点,从该点出发,每一步沿着图中的一条有向边行走。如果到达的节点是终点(即它没有连出的有向边),则停止。
对于一个起始节点,如果从该节点出发,无论每一步选择沿哪条有向边行走,最后必然在有限步内到达终点,则将该起始节点称作是 安全 的。
返回一个由图中所有安全的起始节点组成的数组作为答案。答案数组中的元素应当按 升序 排列。
该有向图有 n
个节点,按 0
到 n - 1
编号,其中 n
是 graph
的节点数。图以下述形式给出:graph[i]
是编号 j
节点的一个列表,满足 (i, j)
是图的一条有向边。
示例 1:
输入:graph = [[1,2],[2,3],[5],[0],[5],[],[]] 输出:[2,4,5,6] 解释:示意图如上。
示例 2:
输入:graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]] 输出:[4]
提示:
n == graph.length
1 <= n <= 104
0 <= graph[i].length <= n
graph[i]
按严格递增顺序排列。- 图中可能包含自环。
- 图中边的数目在范围
[1, 4 * 104]
内。
方法一:深度优先搜索 + 三色标记法
根据题意,若起始节点位于一个环内,或者能到达一个环,则该节点不是安全的。否则,该节点是安全的。
我们可以使用深度优先搜索来找环,并在深度优先搜索时,用三种颜色对节点进行标记,标记的规则如下:
白色(用 00 表示):该节点尚未被访问;
灰色(用 11 表示):该节点位于递归栈中,或者在某个环上;
黑色(用 22 表示):该节点搜索完毕,是一个安全节点。
当我们首次访问一个节点时,将其标记为灰色,并继续搜索与其相连的节点。
如果在搜索过程中遇到了一个灰色节点,则说明找到了一个环,此时退出搜索,栈中的节点仍保持为灰色,这一做法可以将「找到了环」这一信息传递到栈中的所有节点上。
如果搜索过程中没有遇到灰色节点,则说明没有遇到环,那么递归返回前,我们将其标记由灰色改为黑色,即表示它是一个安全的节点。
class Solution {
public:
vector<int> eventualSafeNodes(vector<vector<int>> &graph) {
int n = graph.size();
vector<int> color(n);
function<bool(int)> safe = [&](int x) {
if (color[x] > 0) {
return color[x] == 2;
}
color[x] = 1;
for (int y : graph[x]) {
if (!safe(y)) {
return false;
}
}
color[x] = 2;
return true;
};
vector<int> ans;
for (int i = 0; i < n; ++i) {
if (safe(i)) {
ans.push_back(i);
}
}
return ans;
}
};
以上是关于每日一题802. 找到最终的安全状态的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode802. 找到最终的安全状态(图论三色标记法拓扑排序)/847. 访问所有节点的最短路径(特殊的bfs,状态压缩,dp)
[LeetCode] 802. Find Eventual Safe States 找到最终的安全状态
leetcode 802. 找到最终的安全状态(Find Eventual Safe States)