2021.08.05 LeetCode 802: 拓扑排序

题目大致意思是在一个有向有环图中,若从某个节点开始是无环的状态(以某个节点为起点是有向无环图),那么记录这个节点为安全节点,最后返回安全节点的集合。

我刚拿到题,就从正向开始暴力dfs搜索,顺便用一个circle记录不安全节点,若探索到的节点位于不安全节点集合中,那么在探索的点也必定是不安全点。

但这个思路不可避免要走很多遍graph数组,几乎四O(n2)的,于是超时了。。。

官方题解:拓扑排序,时间复杂O(n+m)

首先介绍拓扑排序,这是对于有向无环图定义的一种排序,有点类似BFS(需要用到队列),但也可以用来判断图中是否存在环。因为根据宫水三叶大神的解析,无环图必然存在入度为0和出度为0的点,否则,每个节点都有前驱or后继节点,那么经过n+1条边,必然经过重复节点,即成环。

拓扑排序一定要从读入为0的节点开始

步骤:
  1. 将所有入度为0的元素加入队列
  2. 弹出队列首元素,遍历所有它出度的节点,将到达的节点入度减一(将现在正在处理的节点从图中剔除)
  3. 若刚才减一操作出现入度为0的情况,push入队列
  4. 循环2.3.步骤,直到队列为空(遍历一遍所有路径)

若是有环图,因为环中元素入度永远不为0,或者说没有办法由已知入度为0的节点逐步剔除,导致他们的入度也为0,没有剔除他们的方法,遍历过后,入度不为0的就是环中元素了

根据题意,要寻找安全节点,安全路径上一定存在出度为0的节点,由前面拓扑排序的方法,可以先构造返图,再由(原来出度=0)现在入度=0的点出发,进行拓扑排序,找到最后入度为0的点,就是安全节点。

代码
class Solution {
public:
    vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
        //返图
        vector<int> ans;
        vector<vector<int>> rg(graph.size());
        vector<int> innode(graph.size(), 0);
        for (int i = 0; i < graph.size(); i++){
            for (auto p : graph[i]){
                rg[p].push_back(i);
            }
            innode[i] = graph[i].size();//源图的出度,反图的入度
        }
        //
        queue<int> q;
        for (int i = 0; i < innode.size(); i++){
            //
            if (innode[i] == 0){
                cout << "i " << i << endl;
                q.push(i);
            }
        }
        cout << q.size();
        //
        while(!q.empty()){
            //
            int node = q.front();
            q.pop();
            for (auto path : rg[node]){
                //
                if (--innode[path] == 0){
                    q.push(path);
                }
            }
        }
        //innode == 0的无环
        for (int i = 0; i < innode.size(); i++){
            if (innode[i] == 0){
                ans.push_back(i);
            }
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值