Leetcode解题笔记 207.Course Schedule [Medium] 拓扑排序

版权声明:自由转载-非商用-非衍生-保持署名 https://blog.csdn.net/mgsweet/article/details/78083424

解题思路

这个星期算法课学了拓扑排序,所以就找了道关于拓扑排序的题来做,其实核心思想就是找DAG(有向无环图),算法的思想就是通过bfs不断去削减节点,并寻找入度为0的点,最后判断所有点是否都变为入度为0的点。具体算法如下:
1. 用一个队列维护所有入度为0的节点,每次弹出一个节点v,查看从v可达的所有节点u;
2. 将u的入读减一,若u的入度此时为0, 则将u加入队列。
3. 在队列为空时,检查所有节点的入度,若所有节点入度都为0, 则存在这样的一个拓扑排序 —— 有向图中不存在环。

例子

例如对于3,[[1, 0], [2, 0], [1, 2]],如图
这里写图片描述

算法第一步,将入度为0的点去掉,变化如下:
这里写图片描述

重复该部,最后所有入度变为0,该图是DAG
而对于有环的图,如图:
这里写图片描述

由于不存在入度为0的点,所以无法找到一个可以入队列的点,所以无法削减。

代码实现

bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
    vector<int> inOrder(numCourses, 0); //用于记录所有顶点的入度数
    vector<vector<int>> map(numCourses); //用vector模拟的邻接链表
    for (int i = 0; i < prerequisites.size(); i++) {
        int priority = prerequisites[i].second;
        int notPriority = prerequisites[i].first;
        inOrder[notPriority]++; //需等待优先节点执行的非优先节点入度+1
        map[priority].push_back(notPriority); //生成邻接链表
    }

    queue<int> q_BFS;
    for (int i = 0; i < numCourses; i++) {
        if (inOrder[i] == 0) q_BFS.push(i);
    }

    int count = q_BFS.size(); // 记录当前入度为0的点的数目

    while(!q_BFS.empty()) {
        for (int i = 0; i < map[q_BFS.front()].size(); i++) {
            int check = --inOrder[map[q_BFS.front()][i]];
            // 若入度削减为0成为root点,则加入队列。
            if (check == 0) {
                count++;
                q_BFS.push(map[q_BFS.front()][i]);
            }
        }
        q_BFS.pop();
    }

    return count == numCourses;
}

猜你喜欢

转载自blog.csdn.net/mgsweet/article/details/78083424