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



相关文章
|
2月前
|
Java
【Java集合类面试二十六】、介绍一下ArrayList的数据结构?
ArrayList是基于可动态扩展的数组实现的,支持快速随机访问,但在插入和删除操作时可能需要数组复制而性能较差。
|
2月前
|
存储 设计模式 算法
JAVA中的常见数据结构
JAVA中的常见数据结构
|
7天前
|
Java
java数据结构,双向链表的实现
文章介绍了双向链表的实现,包括数据结构定义、插入和删除操作的代码实现,以及双向链表的其他操作方法,并提供了完整的Java代码实现。
java数据结构,双向链表的实现
|
7天前
|
存储 Java
java数据结构,线性表链式存储(单链表)的实现
文章讲解了单链表的基本概念和Java实现,包括头指针、尾节点和节点结构。提供了实现代码,包括数据结构、接口定义和具体实现类。通过测试代码演示了单链表的基本操作,如添加、删除、更新和查找元素,并总结了操作的时间复杂度。
java数据结构,线性表链式存储(单链表)的实现
|
2天前
|
存储 安全 Java
Java 数据结构类型总结
在 Java 中,常用的数据结构包括基础数据结构(如数组和字符串)、集合框架(如 Set、List 和 Map 接口的多种实现)、特殊数据结构(如栈、队列和双端队列)、链表(单链表、双链表和循环链表)以及图和树等。这些数据结构各有特点和适用场景,选择时需考虑性能、内存和操作需求。集合框架提供了丰富的接口和类,便于处理对象集合。
|
7天前
|
存储 Java
java数据结构,线性表顺序存储(数组)的实现
文章介绍了Java中线性表顺序存储(数组)的实现。线性表是数据结构的一种,它使用数组来实现。文章详细描述了线性表的基本操作,如增加、查找、删除、修改元素,以及其他操作如遍历、清空、求长度等。同时,提供了完整的Java代码实现,包括MyList接口和MyLinearList实现类。通过main函数的测试代码,展示了如何使用这些方法操作线性表。
|
2月前
|
存储 算法 Java
"解锁Java对象数据结构的奥秘:从基础到实战,与热点技术共舞,让你的编程之路更激情四溢!"
【8月更文挑战第21天】Java以对象为核心,它是程序的基本单元与数据处理的基础。对象源自类,拥有属性(字段)和方法。对象在内存中分为对象头(含哈希码、GC信息等)和实例数据区(存储属性值)。例如,`Student`类定义了姓名、年龄等属性及相应的方法。通过`new`关键字实例化对象并调用其方法进行数据操作,是Java编程的关键技能。
29 0
|
5月前
|
存储 Java
Java数据结构:链表
Java数据结构:链表
41 2
|
4月前
|
算法 Java
Java数据结构与算法:双向链表
Java数据结构与算法:双向链表
|
4月前
|
算法 Java
Java数据结构与算法:循环链表
Java数据结构与算法:循环链表
下一篇
无影云桌面