课程表1
你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1。在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]。给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?
示例 1:
输入: 2, [[1,0]]
输出: true
解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。
示例 2:
输入: 2, [[1,0],[0,1]]
输出: false
解释: 总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0;并且学习课程 0 之前,你还应先完成课程 1。这是不可能的。
import java.util.Scanner;
import java.util.Stack;public class Main{public static void main(String[] args){Scanner sc = new Scanner(System.in); //eg:输入2int numCourse = sc.nextInt();sc.close();int[][] matrix = new int[][]{{1,0},{0,1}};System.out.println(ifFinishCourse(numCourse,matrix));}//函数ifFinishCourse,判断是否可以完成课程public static boolean ifFinishCourse(int numCourse,int[][] matrix){int[] indegree = new int[numCourse];for(int i=0;i<matrix.length;i++){indegree[matrix[i][1]]++;}//创建一个栈Stack<Integer> s = new Stack<>();for(int i=0;i<indegree.length;i++){if(indegree[i] == 0){s.push(i);}}int count = 0; //用于计数,判断是否有环while(!s.isEmpty()){int tempN = s.pop();count++;//更新入度数组for(int i=0;i<matrix.length;i++) {if(matrix[i][0] == tempN){indegree[matrix[i][1]]--;if(indegree[matrix[i][1]] == 0){s.push(matrix[i][1]);}}}}if(count<numCourse){return false;} else {return true;}}
}
课程表2
你这个学期必须选修 numCourse 门课程,记为 0 到 taskNum-1。在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]。给定课程总量以及它们的先决条件,请你判断完成所有课程的学习的最少次数,假设可以并行选修taskNum课程,请计算完成所有课程所需最短时间?
示例 1:
输入: 3
1
1>2
输出: 2
解释: 总共有 3 门课程,选修1个课程。学习课程 1 之前,你需要完成课程 2。总共需要2。
示例 2:
输入:9
6
1>2
2>3
2>4
4>5
6>4
8>7
输出: 4
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;/*** 拓扑排序** @author* @DATE 2024/6/22**/
public class TopologicalSort {public static void main(String[] args) {Scanner cin = new Scanner(System.in, StandardCharsets.UTF_8.name());int taskNum = cin.nextInt();int relationNum = cin.nextInt();int[][] relations = new int[relationNum][];if (relationNum > 0) {cin.nextLine();for (int i = 0; i < relationNum; i++) {String[] str = cin.nextLine().split(">");relations[i] = new int[2];relations[i][0] = Integer.parseInt(str[0]);relations[i][1] = Integer.parseInt(str[1]);}}cin.close();System.out.println(getMinTime(taskNum, relations));}private static int getMinTime(int taskNum, int[][] relations) {/*** 创建拓扑排序* 创建一个入度表* 遍历入度表,把入读为0的全部入队列* 队列出队,判断当前任务的入度是否为0,如果为0,加入队列,遍历完成就是最少次数*/if (taskNum == 0) {return 0;}// 记录每个节点入度int[] num = new int[taskNum];for (int i = 0; i < relations.length; i++) {// 入度指的是一个点被多个边指向num[relations[i][0]]++;}Queue<Integer> queue = new ArrayDeque<>();for (int i = 0; i < taskNum; i++) {// 首先将入度为0的点添加到队列if (num[i] == 0) {queue.add(i);}}int time = 0;while (!queue.isEmpty()) {int size = queue.size();for (int i = 0; i < size; i++) {// 当前节点出队时,将该节点的入度-1int temp = queue.poll();for (int j = 0; j < relations.length; j++) {// relations[j][1]代表依赖节点 == 当前出队节点if (relations[j][1] == temp) {// 当前节点入度-1num[relations[j][0]]--;if (num[relations[j][0]] == 0) {// 入度为0的当前节点,加入队列queue.add(relations[j][0]);}}}}time++;}return time;}
}