(Java)数据结构——图(第九节)AOV网以及拓扑排序

news2024/11/25 23:45:40

前言

本博客是博主用于复习数据结构以及算法的博客,如果疏忽出现错误,还望各位指正。

AOV网

先前我们了解了有向无环图DAG的概念。

所有的工程或者某种流程可以分为若干个小的工程或者阶段,这些小的工程或者阶段就称为活动。若以图中的顶点来表示活动,有向边表示活动之间的优先关系,则这样活动在顶点上的有向图,就称为AOV图(Activity On Vertex Network)。

与AOE网的区别就是:AOE的边是活动(Activity On Edge Network),要不是今天看了下书,我就记混了。

AOV网主要是看工程是否能够顺利进行(拓扑排序判断DAG图,或者其他也行,比如DFS再次碰见isVisited[N] = true等等),AOE则是主要看工程完成所必须的最短时间(关键路径)。

拓扑排序代码实现

原理:找入度为0的,加入栈,然后出栈,遍历它的“链表”,链表里有的结点入度-1,归0后加入栈,依次往复。直到栈里空了,判断一下是不是都遍历了,或者计数也行。都遍历了就是DAG,没遍历完就不是。

517e6de033cd4ab5ad362d8753852312.jpeg

可以看我的另一篇博客,或者直接看实现。

LeetCode 207.课程表——拓扑排序&真真切切建图实现-CSDN博客

应该是没问题的实现(如果出问题,就是搬自己LeetCode时候有的变量名没改)。

package GraphTest.Demo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;

class Test {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        Graph graph = new Graph(numCourses);
        for(int i = 0;i<prerequisites.length;i++){
            //插入结点
            graph.insertEdge(prerequisites[i][0],prerequisites[i][1],1);
        }
        return graph.tuopu();
    }

    public static void main(String[] args) {
        //主要是接收数据麻烦点,其他没啥
        Scanner in = new Scanner(System.in);
        int numCourses = Integer.parseInt(in.nextLine());
        String[] str = in.nextLine().replaceAll("\\[","").replaceAll("]","").split(",");
        int n = str.length / 2;
        int[][] prerequisites = new int[n][2];
        for(int i = 0;i<n;i++){
            prerequisites[i][0] = Integer.parseInt(str[2*i]);
            prerequisites[i][1] = Integer.parseInt(str[2*i+1]);
            System.out.println(prerequisites[i][0]+" "+prerequisites[i][1]);
        }
        System.out.println(canFinish(numCourses,prerequisites));
    }
}

class InData{
    int in;
    int vertex;
    ArrayList<Integer> next = new ArrayList<>();
    InData(int vertex){
        this.in = 0;
        this.vertex = vertex;
    }
}


class Graph{
    int[][] edges;  //边集合
    //ArrayList<Integer> vertexList = new ArrayList<>();  
    //点集合,在这因为没有名称,都是下标,所以不用这个变量
    int numOfEdges;
    InData[] inData;
    boolean[] isVisited;
    Graph(int N){
        this.edges = new int[N][N];
        /*for(int i =0;i<N;i++){
            Arrays.fill(edges[i],Integer.MAX_VALUE);
        }
        然后我之前一弄是54ms,发现是写了好多个打印,一删掉就掉到了13ms
        然后我又发现把这个注释了就从13ms掉到了7ms
        */
        this.numOfEdges = 0;
        this.inData = new InData[N];
        for(int i = 0;i<N;i++){
            inData[i] = new InData(i);
        }
        /*for(int i = 0;i<N;i++){
            vertexList.add(i);
        }*/
        this.isVisited = new boolean[N];
    }
    public void insertEdge(int v1,int v2,int weight){
        this.edges[v1][v2] = weight;
        this.inData[v1].next.add(v2);
        this.inData[v2].in++;
    }
    public boolean tuopu(){//拓扑排序——判断是否能生成一个时间有序的序列
        //一开始我们已经在图中初始化顶点个数个InData类型组成数组,现在我们把他们拷贝过来
        LinkedList<InData> stack = new LinkedList<>();
        InData[] list = new InData[isVisited.length];
        
        for(int i = 0;i<list.length;i++){
            list[i] = inData[i];
            if(list[i].in == 0){//如果发现入度为0就加入栈中
                stack.addFirst(list[i]);
                this.isVisited[i] = true;    //进入栈中的置为已经遍历过
            }
        }
        
        while(!stack.isEmpty()){
            //得到“邻接表”
            ArrayList<Integer> temp = stack.removeFirst().next;
            for(int i:temp){
                //list对应位置的入度-1
                list[i].in--;
                if(list[i].in == 0){
                    //如果对应位置的入度在此刻变成0的话,加入栈中
                    stack.addFirst(list[i]);
                    this.isVisited[i] = true;
                }
            }
        }
        //之后进行判断,如果存在没有遍历过的,直接返回false不能生成
        for(int i = 0;i<isVisited.length;i++){
            if(!isVisited[i]){
                return false;
            }
        }
        return true;
    }
}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1587895.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IPV6的相关网络问题

问题 ​​​​​​​ 目录 问题 一.什么是NAT64转换 1.NAT64的工作原理 IPv6到IPv4转换 IPv4到IPv6的响应转换 2.NAT64的优点 3.NAT64的缺点 二.NAT64转换如何实现 1.工作原理 2.实现步骤 DNS查询转换&#xff08;DNS64&#xff09; 地址转换&#xff08;NAT64&a…

ECharts的时间轴样式设置

timeline: {orient: vertical,axisType: category,autoPlay: false,inverse: true,right: 0,top: 5,bottom: 5,width: 100,realtime : true,symbolSize: 3,itemStyle: { // 轴默认样式color : #000000},checkpointStyle: { // 拖动按钮样式borderWidth: 0,width: 5,color: #7f8…

如何正确使用数字化仪前端信号调理?(一)

一、前言 板卡式的数字转换器和类似测量仪器&#xff0c;比如图1所示的德思特TS-M4i系列&#xff0c;都需要为各种各样的特性信号与内部模数转换器&#xff08;ADC&#xff09;的固定输入范围做匹配。 图1&#xff1a;德思特TS-M4i系列高速数字化仪&#xff0c;包括2或4通道版…

Nacos-默认token.secret.key-配置不当权限绕过漏洞复现

漏洞描述&#xff1a; Nacos 身份认证绕过漏洞(QVD-2023-6271)&#xff0c;开源服务管理平台 Nacos在默认配置下未对 token.secret.key 进行修改&#xff0c;导致远程攻击者可以绕过密钥认证进入后台&#xff0c;造成系统受控等后果。 漏洞信息 公开时间&#xff1a;2023-03…

很难不爱啊!颠覆认知的13个Edge神级插件

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;—…

[Algorithm][双指针][有效三角形的个数]详细解读 + 代码实现

题目链接优化&#xff1a;对整个数组排序&#xff0c;可以简化比较模型&#xff0c;减少比较次数在有序的情况下&#xff0c;只需较⼩的两条边之和⼤于第三边即可设最⻓边枚举到max位置&#xff0c;区间[left, right]是max位置左边的区间(也就是⽐它⼩的区间) if (nums[left] …

前端React笔记(尚硅谷)

react 尚硅谷react教程 jsx语法规则 1.定义虚拟dom时不加引号&#xff08;不是字符串&#xff09; 2.标签中混入js表达式时要用{} js表达式与js语句不同。 js语句是if&#xff08;&#xff09;&#xff0c;for&#xff08;&#xff09;&#xff0c;switch&#xff08;&#x…

花趣短视频源码淘宝客系统全开源版带直播带货带自营商城流量主小游戏

首页设计 仿抖音短视频&#xff1a;采用短视频流的形式展示内容&#xff0c;用户可浏览、点赞、评论和分享短视频。关注与我的&#xff1a;提供用户关注列表和个人中心入口&#xff0c;方便用户管理关注对象和查看个人信息。本地直播&#xff1a;集成直播功能&#xff0c;支持…

小程序如何通过把动态数据值传入到css文件中控制样式

场景&#xff1a;动态改变一个模块的高度 一、常用解决方法&#xff1a;行内样式绑值&#xff0c;或者动态class来传递 <viewclass"box":style"height: ${boxHeight}px">我是一个动态高度的box,我的高度是{{boxHeight}}px </view>二、高度传…

CSS导读 (元素显示模式 下)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 3.6 元素显示模式转换 3.7 (一个小技巧)单行文字垂直居中的代码 3.8 单行文字垂直居中的原理 3.9 小案例…

matlab conv2

MATLAB卷积conv、conv2、convn详解-CSDN博客

Java | Leetcode Java题解之第17题电话号码的字母组合

题目&#xff1a; 题解&#xff1a; class Solution {public List<String> letterCombinations(String digits) {List<String> combinations new ArrayList<String>();if (digits.length() 0) {return combinations;}Map<Character, String> phoneM…

3月产品更新来袭,快来看有没你期待的功能

亮点更新一览 增强制作报表易用性&#xff0c;提升用户体验&#xff0c;如仪表盘图层锁定保持原有层级、即席查询支持批量选择表字段。 增强报表展示和分析能力&#xff0c;满足更多项目需求&#xff0c;如仪表盘表格支持配置是否显示分析菜单按钮、Web电子表格新增多选输入…

Docker镜像,什么是Docker镜像,Docker基本常用命令

docker镜像 1.1什么是镜像&#xff0c;镜像基础 1.1.1 镜像的简介 镜像是一种轻量级&#xff0c;可执行的独立软件包&#xff0c;也可以说是一个精简的操作系统。镜像中包含应用软件及应用软件的运行环境&#xff0c;具体来说镜像包含运行某个软件所需的所有内容&#xff0c;…

【Linux】编写并运行Shell脚本程序操作实例

关于Shell脚本的介绍&#xff1a; Shell脚本是一种用于自动化任务和简化常见操作的脚本语言&#xff0c;通常用于Linux和Unix环境中。Shell脚本允许用户通过编写一系列命令和逻辑语句来执行一系列任务&#xff0c;从而提高了工作效率和自动化水平。 以下是关于Shell脚本的详细…

工业级POE交换机的测试标准

工业级POE交换机的测试标准通常包括以下方面&#xff1a; 1. IEEE 802.3标准&#xff1a;工业级POE交换机遵循IEEE 802.3标准&#xff0c;该标准规定了以太网设备的通信协议和物理层规范。 2. POE标准&#xff1a;工业级POE交换机支持POE&#xff08;Power over Ethernet&…

【软件测试之因果图法】

【软件测试之判断表法】(蓝桥课学习笔记) 1、因果图法的概念 因果图法是一种利用图解法分析输入的各种组合情况&#xff0c;从而设计测试用例的方法&#xff0c;它适合于检查程序输入条件的各种情况的组合。因果图&#xff08;Cause-Effect-Graphing&#xff09;提供了把规则转…

Rust语言

文章目录 Rust语言一&#xff0c;Rust语言是什么二&#xff0c;Rust语言能做什么&#xff1f;Rust语言的设计使其适用于许多不同的领域&#xff0c;包括但不限于以下几个方面&#xff1a;1. 传统命令行程序&#xff1a;2. Web 应用&#xff1a;3. 网络服务器&#xff1a;4. 嵌入…

MySQL选择普通索引还是唯一索引(2/16)

普通索引和唯一索引 基本概述 MySQL中可以创建普通索引与唯一索引&#xff0c;这两种索引的区别是&#xff1a; 普通索引&#xff08;Non-Unique Index&#xff09;&#xff0c;也称为非唯一索引&#xff0c;它允许索引中的条目具有重复的键值。普通索引的主要目的是加快查询…

2024年第十四届MathorCup数学应用挑战赛A题解题思路

2024年第十四届MathorCup数学应用挑战赛A题解题思路点击链接加入【2024年第十四届MathorCup数学建模】&#xff1a; http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kNol416eFZyg4AFPHCZsYfGkLnEnZ8H36&authKeyo9lIFgRfnk2U%2FfYYg1AlFJd5I456CSA2M6nlvJX2qcUockIKuMHj%2Bh…