802-Find Eventual Safe States

本文介绍了一种算法,用于确定有向图中的哪些节点最终是安全的。安全节点是指无论选择哪条路径,最终都能在有限步内达到终点节点的节点。文章提供了一个具体的例子并详细解释了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

In a directed graph, we start at some node and every turn, walk along a directed edge of the graph. If we reach a node that is terminal (that is, it has no outgoing directed edges), we stop.

Now, say our starting node is eventually safe if and only if we must eventually walk to a terminal node. More specifically, there exists a natural number K so that for any choice of where to walk, we must have stopped at a terminal node in less than K steps.

Which nodes are eventually safe? Return them as an array in sorted order.

The directed graph has N nodes with labels 0, 1, …, N-1, where N is the length of graph. The graph is given in the following form: graph[i] is a list of labels j such that (i, j) is a directed edge of the graph.


Example:
Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]]
Output: [2,4,5,6]
Here is a diagram of the above graph.

这里写图片描述


Note:

  • graph will have length at most 10000.
  • The number of edges in the graph will not exceed 32000.
  • Each graph[i] will be a sorted list of different integers, chosen within the range [0, graph.length - 1].

问题描述

在一个有向图中, 我们从某个节点开始并且每轮沿着图中的有向边走动。如果我们到达了某个为终点的节点(出度为0), 就停下

现在, 当前仅当我们最终一定能到达终点时, 我们说我们的起始点最终是安全的。更具体地, 存在一个自然数K, 使得无论我们如何选择行走, 我们都会在K步内到达一个终点。

哪些节点最终安全?将它们作为递增的数组返回

有向图有着标记为0, 1, …, N - 1的N个节点, N为图的长度。图由如下形式给出:graph[i]为j的列表, (i, j)为图中的有向边


问题分析

关键依然是通过color来为节点分组, 0代表未遍历, 1代表最终安全, 2代表已经遍历或者最终不安全

注意2这里的一个值两个用法。可以这样理解, 1代表无论哪条线路都能打通(不存在环), 而2代表当前包含当前节点的线路无法打通(存在环)


解法

class Solution {
    public List<Integer> eventualSafeNodes(int[][] graph) {
        List<Integer> res = new ArrayList();
        if(graph == null || graph.length == 0)  return res;

        int nodeCount = graph.length;
        int[] color = new int[nodeCount];

        for(int i = 0;i < nodeCount;i++){
            if(dfs(graph, i, color))    res.add(i);
        }

        return res;
    }
    public boolean dfs(int[][] graph, int start, int[] color){
        if(color[start] != 0)   return color[start] == 1;

        color[start] = 2;
        for(int newNode : graph[start]){
            //若该节点存在一条边, 其对应的顶点无法走通, 那么之前递归的所有节点都为2
            if(!dfs(graph, newNode, color))    return false;
        }
        //注意这里的变换, 当该节点对应的边的所有节点都能打通, 那么该节点可以打通, 即最终安全
        color[start] = 1;

        return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值