leetcode [Graph] No.207 Course Schedule

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Richard_M_pu/article/details/82904615

题目描述

There are a total of n courses you have to take, labeled from 0 to n-1.

Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

Example1:

Input: 2, [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.

Example2:

Input: 2, [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.

Note:

  1. The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
  2. You may assume that there are no duplicate edges in the input prerequisites.

解题思路

该问题中,我们可以根据课程学习的先后顺序构建一张有向图,其中,若课程a必须在修完课程b后才可以学习,那么该有向图中有一条边,由b指向a。在构建完有向图之后,该问题便变成了有向图中是否存在一个环,若存在环,便无法学习完所有课程,反之亦然。我们可以使用拓扑排序算法简单、高效的判断一个有向图中是否存在一个环,时间复杂度为 O ( n + e ) O(n+e) ,其中 n n 表示顶点个数, e e 表示边的个数。

拓扑排序步骤

  1. 遍历图中所有的边,记录下每个定点的入度
  2. 遍历所有定点的入度,将入度为0的顶点压入一个队列。
  3. 当队列不为空时,抛出队列中第一个元素,否则跳到步骤5.
  4. 将所有从抛出点可到达的顶点的入度减一,若某个点的入度为0,则加入队列尾部。循环辉步骤3。
  5. 检查所有定点的入度,若存在一个顶点入度不为0,则该有向图存在环,否则不存在。

代码:

class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        //新建队列
        queue<int> q;
        //初始化有向图
	    bool map[numCourses][numCourses] = {};
	    //记录顶点入度的数组
        int in[numCourses] = {};
        //根据输入构建有向图
        for (auto iter : prerequisites) {
        	map[iter.second][iter.first] = true;
        	in[iter.first]++;
		}
		
		//入度为0的点入队
		for (int i = 0; i < numCourses; i++) {
			if (in[i] == 0) {
				q.push(i);
			}
		}
	
		//循环求解
		while(!q.empty()) {
			int course = q.front();
			q.pop();
			for (int i = 0; i < numCourses; i++) {
				if (map[course][i]) {
					if (--in[i] == 0) {
						q.push(i);
					}
				}
			}
		}
		
		//检查是否还存在入度不为0的点
		for (int i = 0; i < numCourses; i++) {
			if (in[i] != 0) return false;
		}
		return true;
    }
};

运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Richard_M_pu/article/details/82904615