• 【数据结构】F:B DS图_课程表 拓扑排序实现


    F : B DS图_课程表

    Description

    小明这个学期必须选修n门课程,课程编号记为0到n-1。
    在选修某些课程之前需要一些先修课程。先修课程按数组prerequisites给出,其中prerequisites[i] = [a, b],表示如果要学习课程a则必须先学习课程b。
    例如,先修课程对[0, 1]表示:要想学习课程0,则需要先完成课程1。
    请判断小明能否完成所有课程的学习,如果可以则输出true,否则输出false。

    Input

    第一行输入t,表示有t个测试样例。
    接着输入n,表示有n门课程,接着输入len,表示prerequisites数组的长度,接着输入prerequisites数组。
    以此类推,共输入t个测试样例。

    Output

    每一行输出能否完成所有课程的学习,若可以则输出true,否则输出false。
    共输出t行。

    输入样例:

    3
    
    2
    1
    1 0
    
    2
    2
    1 0
    0 1
    
    3
    3
    1 0
    2 0
    2 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    输出样例:

    true
    false
    true
    
    • 1
    • 2
    • 3

    Hint

    1 <= n <= 10^5
    len == prerequisites.length
    1 <= len <= 5000
    prerequisites[i].length == 2
    0 <= a, b < n
    prerequisites中的所有课程对互不相同。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    解题思路:

    这个问题可以通过拓扑排序来解决。我们需要检查给定的先修课程列表(prerequisites)是否会形成一个有向图中的环。如果有环存在,那么小明就无法完成所有课程(因为有环意味着存在无法满足的先修条件)。拓扑排序可以帮助我们检测这样的环。因为它会把所有入度等于0的节点给挑走,所以它会留下环!如果是一个环的话,即使拓扑排序把其他入度为0的节点给挑走,它的入度也不会是0的,如果完成的课程数量等于课程总数,则返回true,否则返回false

    AC代码

    #include 
    #include 
    using namespace std;
    
    // SZTU forever!!!
    // SZTU forever!!!
    // SZTU forever!!!
    
    bool canFinish(int numCourses, int** prerequisites, int preLen) {
        int* inDegree = new int[numCourses]();
        int** graph = new int* [numCourses];
        for (int i = 0; i < numCourses; ++i) {
            graph[i] = new int[numCourses]();
        }
    
        // 建立图并计算入度
        for (int i = 0; i < preLen; ++i) {
            int a = prerequisites[i][0];
            int b = prerequisites[i][1];
            graph[b][a] = 1; // 有向图的边
            inDegree[a]++;
        }
    
        queue<int> q;
        // 将所有入度为0的课程加入队列
        for (int i = 0; i < numCourses; ++i) {
            if (inDegree[i] == 0) {
                q.push(i);
            }
        }
    
        // 执行拓扑排序
        int count = 0;
        while (!q.empty()) {
            int current = q.front();
            q.pop();
            count++;
            for (int i = 0; i < numCourses; ++i) {
                if (graph[current][i] == 1 && --inDegree[i] == 0) {
                    q.push(i);
                }
            }
        }
    
        // 清理资源
        for (int i = 0; i < numCourses; ++i) {
            delete[] graph[i];
        }
        delete[] graph;
        delete[] inDegree;
    
        // 如果计数等于课程数,说明可以完成所有课程
        return count == numCourses;
    }
    
    int main() {
        int t;
        cin >> t;
        while (t--) {
            int n, len;
            cin >> n >> len;
            int** prerequisites = new int* [len];
            for (int i = 0; i < len; ++i) {
                prerequisites[i] = new int[2];
                cin >> prerequisites[i][0] >> prerequisites[i][1];
            }
    
            cout << (canFinish(n, prerequisites, len) ? "true" : "false") << endl;
    
            for (int i = 0; i < len; ++i) {
                delete[] prerequisites[i];
            }
            delete[] prerequisites;
        }
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
  • 相关阅读:
    搜素专题(DFS )
    JavaScript动态设置浏览器可视区域元素的文字颜色、监听滚动条、querySelectorAll、getBoundingClientRect
    golang GC
    webpack5 Core-js解决async 函数、promise 对象等兼容问题
    CMake中搜索文件的两种方式
    Go语言实践案例之简单字典
    MySQL表的约束
    从云计算到函数计算
    cmd安装jupyter出错
    SCI写作指南
  • 原文地址:https://blog.csdn.net/likinguuu/article/details/134451800