【数据结构】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

输出样例:

true
false
true

Hint

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

解题思路:

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

AC代码

cpp 复制代码
#include <iostream>
#include <queue>
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;
}
相关推荐
ZZZ_O^O17 分钟前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
CV-King40 分钟前
opencv实战项目(三十):使用傅里叶变换进行图像边缘检测
人工智能·opencv·算法·计算机视觉
代码雕刻家1 小时前
数据结构-3.9.栈在递归中的应用
c语言·数据结构·算法
雨中rain1 小时前
算法 | 位运算(哈希思想)
算法
Kalika0-03 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
代码雕刻家3 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
sp_fyf_20243 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02
人工智能·神经网络·算法·计算机视觉·语言模型·自然语言处理·数据挖掘
小字节,大梦想4 小时前
【C++】二叉搜索树
数据结构·c++
我是哈哈hh5 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
Tisfy5 小时前
LeetCode 2187.完成旅途的最少时间:二分查找
算法·leetcode·二分查找·题解·二分