leetcode802——Find Eventual Safe States

题目大意:从一个结点出发,最终能走到一个没有出边的点,那么这个起始点称为安全点。给出有向图的邻接表,问图里哪些点是安全点。

分析:

方法一:dfs。这道题的意思就是看从哪些点出发没有能回到原点的环存在。给图中的结点上色,初始化为0号色(color[i]=0表示没访问过该结点),dfs时遍历到的结点染1号色(表示访问过该节点),遍历邻接表判断如果无环则该节点染2号色(表示安全无环)。

方法二:拓扑排序。安全节点=无出边。将图中的所有边反向(注意题中给的graph是邻接表,不是leetcode210中给出的边集合),此时安全节点=无入边的点(入度为0),与安全节点相连的点也是安全节点,所以将入度为0的点和它的出边删掉后,剩下的入度为0的点也是安全节点,这一过程就是拓扑排序的过程。

代码:

方法一:dfs

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))                                                                                                                                                                                
                ans.push_back(i);          
        }        
        return ans;    
    }    
    bool dfs(int i,vector<int>& color,vector<vector<int>>& graph){        
        if(color[i]) return color[i] == 2;  //如果染色是安全状态2就返回true        
        color[i] = 1;  //初始染1号色,相当于标记这次dfs过程中访问过它,但它的状态不确定是否安全                         
        for(auto nei : graph[i]){  
            // 邻接节点不安全 || 邻接节点的邻接节点不安全
            if(color[nei] == 1 || !dfs(nei,color,graph))                
                return false;        
        }        
        color[i] = 2;        
        return true;    
    }
};

方法二:拓扑排序

class Solution {
public:
    vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
        vector<vector<int>> pre(graph.size());  //记录每个节点的后续结点
        vector<int> degree(graph.size(),0);  //记录每个结点的入度
        for (int i = 0;i < graph.size();i++) {
            for(int j = 0;j < graph[i].size();j++){
                degree[i]++;
                pre[graph[i][j]].push_back(i);
            }
        }
        queue<int> q;  //队列维护入度为0的结点
        for(int i = 0;i < graph.size();i++){
            if(degree[i] == 0) q.push(i);
        }
        vector<int> schedule;
        while(!q.empty()){
            int now = q.front();
            q.pop();
            schedule.push_back(now);
            for(int i = 0;i < pre[now].size();i++){
                degree[pre[now][i]]--;
                if(degree[pre[now][i]] == 0) q.push(pre[now][i]);
            }
        }
        sort(schedule.begin(),schedule.end());
        return schedule;
    }
};

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值