802. Find Eventual Safe States

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.

思路:本题想要找的是能够不陷入死循环的节点的个数,那么在一个循环里面的节点都是不安全的。对于一个节点来说,如果他的相邻子节点都是安全的那么他就是安全的。那么目前的问题是,访问时节点有三个状态,1.未访问 2.访问但不确定安全不安全3.安全。

深度优先搜索

最开始进入一个节点时,做以下判断:

1.如果它被访问过,那么直接返回它是否是安全的。

2.如果没有被访问,那么先把他设置为已经访问,遍历他的子节点,如果他的子节点的状态为已经访问但不是安全,或者进行深度搜索没有问题,那么设置为安全状态,返回true.否则返回false。

Code:

class Solution {
public:
    vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
        int n = graph.size();
        vector<int> color(n);
        vector<int> ans;
        for(int i = 0;i < n;i++){  //dfs每个结点判断是否有环
            if(dfs(i,color,graph))  //从i出发有环则返回false
                ans.push_back(i);  
        }
        return ans;
    }
    bool dfs(int i,vector<int>& color,vector<vector<int>>& graph){
        if(color[i]!=0) return color[i] == 2;  //如果染色是安全状态2就返回true
        color[i] = 1;  //初始染1号色,相当于标记这次dfs过程中访问过它,但它的状态不确定是否安全
        for(auto nei : graph[i]){  //如果它的邻接点或者他的邻接点的邻接点dfs时又访问了i结点那么就说明成环了。
            if(color[nei] == 1 || !dfs(nei,color,graph))
                return false;
        }
        color[i] = 2;
        return true;
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值