用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);
    }
}



相关文章
|
3月前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
55 1
|
3月前
|
存储 Java
告别混乱!用Java Map优雅管理你的数据结构
【10月更文挑战第17天】在软件开发中,随着项目复杂度增加,数据结构的组织和管理至关重要。Java中的Map接口提供了一种优雅的解决方案,帮助我们高效、清晰地管理数据。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,有效提升了代码质量和维护性。
97 2
|
21天前
|
存储 缓存 安全
Java 集合江湖:底层数据结构的大揭秘!
小米是一位热爱技术分享的程序员,本文详细解析了Java面试中常见的List、Set、Map的区别。不仅介绍了它们的基本特性和实现类,还深入探讨了各自的使用场景和面试技巧,帮助读者更好地理解和应对相关问题。
37 5
|
2月前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
53 6
|
2月前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
3月前
|
存储 算法 Java
Java 中常用的数据结构
【10月更文挑战第20天】这些数据结构在 Java 编程中都有着广泛的应用,掌握它们的特点和用法对于提高编程能力和解决实际问题非常重要。
36 6
|
3月前
|
存储 Java 开发者
Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效
【10月更文挑战第19天】在软件开发中,随着项目复杂度的增加,数据结构的组织和管理变得至关重要。Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,帮助开发者告别混乱,提升代码质量。
37 1
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
236 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
37 1
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
69 5

热门文章

最新文章