用Java写数据结构作业——7-2 任务调度的合理性 (25分)

简介: 用Java写数据结构作业——7-2 任务调度的合理性 (25分)

7-2 任务调度的合理性 (25分)

假定一个工程项目由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其它一些子任务后才能执行。“任务调度”包括一组子任务、以及每个子任务可以执行所依赖的子任务集。

比如完成一个专业的所有课程学习和毕业设计可以看成一个本科生要完成的一项工程,各门课程可以看成是子任务。有些课程可以同时开设,比如英语和C程序设计,它们没有必须先修哪门的约束;有些课程则不可以同时开设,因为它们有先后的依赖关系,比如C程序设计和数据结构两门课,必须先学习前者。

但是需要注意的是,对一组子任务,并不是任意的任务调度都是一个可行的方案。比如方案中存在“子任务A依赖于子任务B,子任务B依赖于子任务C,子任务C又依赖于子任务A”,那么这三个任务哪个都不能先执行,这就是一个不可行的方案。你现在的工作是写程序判定任何一个给定的任务调度是否可行。

输入格式:

输入说明:输入第一行给出子任务数N(≤100),子任务按1~N编号。随后N行,每行给出一个子任务的依赖集合:首先给出依赖集合中的子任务数K,随后给出K个子任务编号,整数之间都用空格分隔。

输出格式:

如果方案可行,则输出1,否则输出0。

输入样例1:


12

0

0

2 1 2

0

1 4

1 5

2 3 6

1 3

2 7 8

1 7

1 10

1 7


输出样例1:

1


输入样例2:

51 42 1 42 2 51 30


输出样例2:

0


此题虽然复杂,但好在只叫我们判断是否构成回路。


解决此题我们需要一个问题——如何才能判断是否构成回路?


这有一个思路:首先把入度为零的结点逐个输出,在输出的同时删除以它为起始点的边,如此循环操作,到最后如果还有点剩下,那么剩下的点就构成回路


根据这个思路,我们可以把程序分为以下几步:

1.根据输入建图(这里一般采用邻接表更好,但为了方便我采用邻接矩阵来表示)

2.遍历图,进行拓扑排序,同时让以它为起点的结点入度减一(相当于删除以它为起始点的边)

注:我们设置inner数组存储入度

3.循环遍历结束,判断inner数组中是否是否所有数都为0,若没有则输出0(表示方案不可行,若全为0则方案可行)


import java.util.Scanner;
public class Main {
    //表示无穷大
    final static int MaxInt=1000;
    static int num;
    static int[][] Graph;
    public static void main(String[] args) {
        initialize();
        topSort();
    }
//    1.根据输入建图(这里一般采用邻接表更好,但为了方便我采用邻接矩阵来表示)
    private static void initialize(){
        int temp,node;
        Scanner scanner=new Scanner(System.in);
        //存储结点个数
        num=scanner.nextInt();
        Graph=new int[num][num];
        for (int i=0;i<num;i++){
            for (int j=0;j<num;j++){
                Graph[i][j]=MaxInt;
            }
        }
        //这里我看错题目了,我以为每行第一个也是数据,结果是表示个数。。。。。唉,所以下次做题前还是先把题目细节弄清楚再来做题
//        //注意:读取完会有“”,这会导致无法转换,所以先把这个""消耗掉
//        scanner.nextLine();
//        for (int i=0;i<num;i++){
//            //记录每行的字符串
//            String line=scanner.nextLine();
//            String[] nodes=line.split(" ");
//            for (String s:nodes){
//
//                //同时0表示无节点,所以也要排除
//                if (!s.equals("0")){
//                    //记录转化后的数
//                    temp=Integer.parseInt(s);
//                    //将有边的结点赋值为1,并且它指的结点值减一才为下标值
//                    Graph[temp-1][i]=1;
//                }
//
//            }
//        }
        for (int i=0;i<num;i++){
            temp=scanner.nextInt();
            for (int j=0;j<temp;j++){
                node=scanner.nextInt();
                Graph[node-1][i]=1;
            }
        }
    }
    private static void topSort(){
        //    2.遍历图,进行拓扑排序,同时让以它为起点的结点入度减一(相当于删除以它为起始点的边)
        //    注:我们设置inner数组存储入度
        //    3.循环遍历结束,判断inner数组中是否是否所有数都为0,若没有则输出0(表示方案不可行,若全为0则方案可行)
        //不需要初始化,因为创建数组时默认值就为0
        int[] inner=new int[num];
        //记录结点是否被收录,0表示未被收录,1表示已被收录
        int[] collected=new int[num];
        //为inner数组赋值
        for (int i = 0; i<num; i++){
            for (int j=0;j<num;j++){
                if (Graph[i][j]==1){
                    inner[j]++;
                }
            }
        }
        //定义开关
        boolean flag=true;
        while (flag){
            //记录此次遍历时收录结点的格式
            int count=0;
            for (int i=0;i<num;i++){
                if (inner[i]==0&&collected[i]==0){
                    collected[i]=1;
                    count++;
                    for (int j=0;j<num;j++){
                        if (Graph[i][j]==1){
                            inner[j]--;
                        }
                    }
                }
            }
            //若count为0表示此次循环未收录结点,可退出循环
            if (count==0){
                flag=false;
            }
        }
        for (int i=0;i<num;i++){
            if (inner[i]!=0){
                System.out.println(0);
                return;
            }
        }
        System.out.println(1);
    }
}



相关文章
|
1月前
|
Java
Java基础学习day08-作业
本作业涵盖Java中Lambda表达式的应用,包括Runnable与Comparator接口的简化实现、自定义函数式接口NumberProcessor进行加减乘及最大值操作,以及通过IntProcessor处理整数数组,实现遍历、平方和奇偶判断等功能,强化函数式编程实践。
55 5
|
1月前
|
Java
Java基础学习day07-作业
本作业包含六个Java编程案例:1)动物类继承与多态;2)加油卡支付系统;3)员工管理类设计;4)学生信息统计接口;5)USB设备控制;6)家电智能控制。综合运用抽象类、接口、继承、多态等面向对象技术,强化Java基础编程能力。
150 3
|
1月前
|
Java
Java基础学习day06-作业
本内容为Java基础学习作业,涵盖两个案例:一是通过Card类及其子类GoldenCard、SilverCard实现加油卡系统,体现封装与继承;二是通过Shape类及子类Circle、Rectangle演示多态与方法重写,强化面向对象编程理解。
52 1
|
1月前
|
Java
Java基础学习day05-作业
本文为Java基础学习第五天作业,通过五个案例练习类与对象的定义、构造方法、set/get方法及成员方法的应用。涵盖女友、学生、教师、手机和电影等类的设计与测试,强化面向对象编程基础。
60 2
|
1月前
|
Java
Java基础学习day04-作业
本作业包含8个Java编程案例,涵盖数组的定义与遍历、求和、最值计算、去极值求平均、元素倍增、二维数组行和计算及查找指定元素等内容,旨在巩固Java基础语法与数组操作技能。
178 1
|
1月前
|
算法 Java
Java基础学习day03-作业
本内容包含多个Java编程案例,涵盖条件判断、循环、数组、随机数生成、素数判断等基础算法练习,适用于巩固Java语法与逻辑思维训练。
94 6
|
1月前
|
Java
Java基础学习day02-作业
本内容包含13个Java编程练习需求,涵盖变量定义、数据类型转换、运算符使用、键盘输入及条件判断等基础语法实践,适合初学者巩固Java核心基础知识。
61 5
|
Java
Java基础学习day01-作业
通过多个Java编程案例,学习变量定义、数据类型使用及控制台输出。涵盖字符串、数值、布尔值等字面量输出,变量赋值与修改,以及实际应用场景如学生信息和商品价格变化的模拟,夯实基础语法掌握。
57 0
|
4月前
|
机器学习/深度学习 存储 算法
Java 大视界 -- Java 大数据在智能农业无人机植保作业路径规划与药效评估中的应用(165)
本文围绕 Java 大数据在智能农业无人机植保作业路径规划与药效评估中的应用展开,剖析作业现状与挑战,阐述技术原理及应用方法,结合案例与代码,给出具有实操性的解决方案。
Java 大视界 -- Java 大数据在智能农业无人机植保作业路径规划与药效评估中的应用(165)
|
4月前
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
221 3