【数据结构与算法】——第六章:图

news2024/11/28 5:39:39

文章目录

      • 1、图的定义
        • 1.1 图的其他定义
        • 1.2 图的顶点与边之间的关系
        • 1.3 连通图相关术语
      • 2、图的存储结构
        • 2.1 邻接矩阵
        • 2.2 邻接表
      • 3、图的遍历
        • 3.1 深度优先遍历
        • 3.2 广度优先遍历
      • 4、最小生成树
        • 4.1 普利姆算法(Prim)
        • 4.2 克鲁斯卡尔(kruskal)
      • 5、最短路径
        • 5.1 迪杰斯特拉(Dijkstra)算法
        • 5.2 弗洛伊德(Floyd)算法
      • 6、拓扑排序
      • 7、关键路径

 ============================ 【说明】 ===================================================
  大家好,本专栏是 数据结构与算法该科目是计算机类专业必修课之一,比较重要也比较基础,有想从事算法研究的同学,这些内容是专/本科、甚至硕士期间较为基础的内容,适用范围较广:大学专业课学习、考研复习等。
  通过自己的理解进行整理,希望大家积极交流、探讨,多给意见。后面也会给大家更新其他一些知识。若有侵权,联系删除!共同维护网络知识权利!


1、图的定义

  在线性表中,数据元素之间是被串起来的,仅有线性关系,每个数据元素只有一个直接前驱和一个直接后继。
  在树形结构中,数据元素之间有着明显的层次关系,并且每一层上的数据元素可能和下一层中多个元素相关,但只能和上一层中一个元素相关。这和一对父母可以有多个孩子,但每个孩子却只能有一对父母是一个道理。

  可现实中,人与人之间关系就非常复杂,比如我认识的朋友,可能他们之间也互相认识,这就不是简单的一对一、一对多,研究人际关系很自然会考虑多对多的情况

  今天要研究的主题一一图是一种较线性表和树更加复杂的数据结构。在图形结构中,结点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关。

   图(Graph) 是由顶点的有穷非空集合顶点之间边的集合组成,通常表示为:G ( V,E )其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合

  
   对于图的定义,我们需要明确几个注意的地方:

   1、线性表中我们把数据元素叫元素中将数据元素叫结点,在中数据元素,我们则称之为顶点(Vertex)
   2、线性表中可以没有数据元素,称为空表中可以没有结点,叫做空树。那么对于图呢?在图结构中,不允许没有顶点。在定义中,若v是顶点的集合,则强调了顶点集合v有穷非空。
   3、线性表中,相邻的数据元素之间具有线性关系树结构中,相邻两层的结点具有层次关系;而图中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边来表示,边集可以是空的。

  

1.1 图的其他定义

   (1) 无向图与有向图

  无向边:若顶点到顶点之间的边没有方向,则称这条边为无向边,用无序偶对(vi,vj)来表示。如果图中任意两个顶点之间的边都是无向边,则称该图为无向图
  下图就是一个无向图,由于是无方向的,连接顶点A 与D的边,可以表示成无序对(A,D),也可以写成(D,A)。对于下图中的无向图G1来说,G1= (V1,{E1}),其中顶点集合V1={A,B,C,D}边集合E1={ (A,B),(B,C), (C,D),(D,A) , (A,C) }

  有向边:若从顶点到顶点的边有方向,则称这条边为有向边,也称为。用有序偶<vi,vj>来表示,vi称为弧尾vj称为弧头如果图中任意两个顶点之间的边都是有向边,则称该图为有向图
  下图就是一个有向图。连接顶点A到D的有向边就是弧,A弧尾D弧头<A,D>表示弧,注意不能写成<D,A>。对于下图中的有向图G2来说,G2=(V2,{E2}),其中顶点集合V2={A,B,C,D},弧集合E2={<A,D>,<B,A>,<C,A>,<B,C>}

  注意:无向边用小括号“()”表示,而有向边则是用尖括号“<>”表示。

  
   (2) 无向完全图与有向完全图

   在无向图中如果任意两个顶点之间都存在边,则称该图为无向完全图。含有n 个顶点的无向完全图有n*(n-1)/2条边。

  例:下图就是无向完全图,因为每个顶点都要与除它以外的顶点连线,顶点A与BCD三个顶点连线,共有四个顶点,自然是4 × 3,但由于顶点A与顶点B连线后,计算B与A连线就是重复,因此要整体除以2,共有6条边。

   在有向图中如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向完全图。含有n个顶点的有向完全图有n (n-1)条边,如下图所示。

  总结:从这里也可以得到结论,对于具有n个顶点和e条边数的图,无向图0 ≤ e ≤ n *(n -1) /2,有向图0 ≤ e ≤n*(n-1)

  
   (3) 稀疏图、稠密图、网

   有很少条边或弧的图称为稀疏图,反之称为稠密图这里稀疏和稠密是模糊的概念,都是相对而言的
   有些图的边或弧具有与它相关的数字,这种与图的边或弧相关的数叫做这些权可以表示从一个顶点到另一个顶点的距离或耗费
   这种带权的图通常称为。下图就是一张带权的图,即标识中国四大城市的直线距离的网,此图中的权就是两地的距离。

  
   (4) 子图

   假设有两个图G= (V,{E})G'= (V'{E’}),如果V'⊆V且U'⊆UG'G的子图

   例下图带底纹的图均为左侧无向图与有向图的子图

  

1.2 图的顶点与边之间的关系

   (1) 度

   对于无向图G= (V,{E}),如果边(v,v’)∈E,则称顶点vv'互为邻接点,即v和v’相邻接。边(v,v’)依附于顶点vv’,或者说 (v,v’)与顶点vv'相关联。

   无向图顶点v的度是和v相关联的边的数目,记为 TD (v)

   例如:下图的无向图,顶点A与B互为邻接点,边(A,B)依附于顶点A与B上,顶点A的度为3。而此图的边数是5,各个顶点度的和 =3+ 2+ 3 +2= 10,推敲后发现,边数其实就是各顶点度数和的一半,多出的一半是因为重复两次记数。

   对于有向图G= (V,{E}),如果弧<v,v'>∈ E,则称顶点v邻接到顶点v’顶点v’邻接自顶点v。弧<v,v'>顶点v,v’相关联

   以顶点v为头的弧的数目称为 v的入度,记为ID (v);
   以v为尾的弧的数目称为v的出度,记为 OD (v);
  有向图顶点v的度TD (v) =ID (v) +0D (v)

   例如:下图的有向图,顶点A的入度是2(从B到A的弧,从C到A的弧),出度是1(从A到D的弧),所以顶点A的度为2+ 1=3。

  
   (2) 路径

  无向图G= (V,{E))中从顶点v到顶点v’的路径是一个顶点序列。例如下图中就列举了顶点B到顶点D四种不同的路径:

  如果G是有向图,则路径也是有向的,例如下图,顶点B到D有两种路径。而顶点A到B,就不存在路径:

   注:树中根结点到任意结点的路径是唯一的,但是图中顶点与顶点之间的路径却是不唯一。

  
   (3) 其他

  路径的长度是路径上的边或弧的数目
  第一个顶点到最后一个顶点相同的路径称为回路或环
  序列中顶点不重复出现的路径称为简单路径
  除了第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路,称为简单回路或简单环

  下图中两个图的粗线都构成环,左侧的环因第一个顶点和最后一个顶点都是B,且C、D、A没有重复出现,因此是一个简单环。而右侧的环,由于顶点C的重复,它就不是简单环了。

  

1.3 连通图相关术语

   在无向图G中,如果从顶点v到顶点v’有路径,则称v和v’是连通的
   如果对于图中任意两个顶点、vi、vj∈ Evi和vj都是连通的,则称G是连通图

   例如:下图的图1,它的顶点A到顶点B、C、D都是连通的,但显然顶点A与顶点E或F就无路径,因此不能算是连通图。而图2,顶点A、B, C、 D相互都是连通的,所以它本身是连通图。

   无向图中的极大连通子图称为连通分量。注意连通分量的概念,它强调:

   1、要是子图;
   2、子图要是连通的,
   3、连通子图含有极大顶点数
   4、具有极大顶点数的连通子图包含依附于这些顶点的所有边。

   例如:下图的图1是一个无向非连通图。但是它有两个连通分量,即图2和图3。而图4,尽管是图1的子图,但是它却不满足连通子图的极大顶点数(图2满足)。因此它不是图1的无向图的连通分。

   在有向图G中,如果对于每一对vi、vj∈ E从vi到vj和从vj到vi都存在路径,则称G是强连通图
   有向图中的极大强连通子图称做有向图的强连通分量

   例如:下图1并不是强连通图,因为顶点A到顶点D存在路径,而D到A就不存在。图2不是强连通图,而且显然图2是图1的极大强连通子图,即是它的强连通分量。


2、图的存储结构

   图的存储结构相比较线性表与树来说就更加复杂了。
   首先,我们口头上说的“顶点的位置”或“邻接点的位置"只是一个相对的概念。其实从图的逻辑结构定义来看图上任何一个顶点都可被看成是第一个顶点,任一顶点的邻接点之间也不存在次序关系

   比如下图的四张图,仔细观察发现,它们其实是同一个图,只不过顶点的位置不同,就造成了表象上不太一样的感觉。

   也正由于图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在内存中的物理位置来表示元素之间的关系,也就是说,图不可能用简单的顺序存储结构来表示

   对于图来说,如何对它实现物理存储是个难题,但是已经解决,以下提供多种不同的存储结构

  

2.1 邻接矩阵

   考虑到图是由顶点和边或弧两部分组成。合在一起比较困难,那就很自然地考虑到分两个结构来分别存储

  顶点不分大小、主次,所以用一个一维数组来存储是很不错的选择。而边或弧由于是顶点与顶点之间的关系,一维搞不定,那就考虑用一个二维数组来存储。于是我们的邻接矩阵的方案就诞生了。

   图的邻接矩阵存储方式是用两个数组来表示图:一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。

   设图G有n个顶点,则邻接矩阵是一个nXn的方阵,定义为:

   例如:下图就是一个无向图:

   我们可以设置两个数组,顶点数组vertex[4] ={ v0,v1,v2,v3}边数组arc[4][4]为上图图这样的一个矩阵。解释一下矩阵,无向图的边数组是一个对称矩阵

  有了这个矩阵,我们就可以很容易地知道图中的信息

  1、我们要判定任意两顶点是否有边无边就非常容易了;
  2、我们要知道某个顶点的度,其实就是这个顶点vi在邻接矩阵中第i行(或第i 列)的元素之和。比如顶点V1的度就是1+0+ 1+0=2;
  3、求顶点Vi的所有邻接点就是将矩阵中第i行元素扫描一遍,arc[i][j]为1就是邻接点。


   例如:我们再来看一个有向图样例,如下图:

   有向图讲究入度与出度,顶点v1的入度为1,正好是第v1列各数之和。顶点v1的出度为2,即第V1行的各数之和。

   与无向图同样的办法,判断顶点到vj是否存在弧,只需要查找矩阵中arc[i][j]是否为1即可。要求Vi的所有邻接点就是将矩阵第i行元素扫描一遍,查找arc [i][j] 为1的顶点。


   前面在图的概念中,我们提到了网的概念。也就是每条边上带有权的图叫做。那么这些权值就需要存下来,如何处理这个矩阵来适应这个需求呢?

  设图G是网图,有n个顶点,则邻接矩阵是一个 n*n的方阵,定义为:

  这里表示(vi,vj)<vi,vj>上的权值。表示一个计算机允许的、大于所有边上权值的值,也就是一个不可能的极限值。下图的左图就是一个有向网图,右图就是它的邻接矩阵:

  

2.2 邻接表

   邻接矩阵是不错的一种图存储结构,但是我们也发现,对于边数相对顶点较少的图,这种结构是存在对存储空间的极大浪费的。 比如说:如果我们要处理下图这样的稀疏有向图,邻接矩阵中除了arc[1][0]有权值外,没有其他弧,其实这些存储空间都浪费掉了。

   因此我们考虑另外一种存储结构方式:

   回忆下在 线性表时谈到,顺序存储结构就存在预先分配内存可能造成存储空间浪费的问题,于是引出了链式存储的结构。同样的,我们也可以考虑对边或弧使用链式存储的方式来避免空间浪费的问题。

   再回忆在 中谈存储结构时,讲到了一种孩子表示法,将结点存入数组,并对结点的孩子进行链式存储,不管有多少孩子,也不会存在空间浪费问题。

   以上两种思路同样适用于图的存储。我们把这种数组与链表相结合的存储方法称为 邻接表

   邻接表的处理办法是这样

   1、图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过数组可以较容易地读取顶点信息,更加方便。另外,对于顶点数组中,每个数据元素还需要存储指向第一个邻接点的指针,以便于查找该顶点的边信息。
   2、图中每个顶点Vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以用单链表存储,无向图称为顶点的边表,有向图则称为顶点作为弧尾的出边表

   例如:下图所示的就是一个无向图的邻接表结构:

   从图中我们知道,顶点表的各个结点由datafirstedge两个域表示。data数据域,存储顶点的信息;firstedge指针域,指向边表的第一个结点,即此顶点的第一个邻接点。

   边表结点adjvexnext两个域组成。adjvex邻接点域,存储某顶点的邻接点在顶点表中的下标;next则存储指向边表中下一个结点的指针。

  这样的结构,对于我们要获得图的相关信息也是很方便的:
  1、比如我们要想知道某个顶点的度,就去查找这个顶点的边表中结点的个数。
  2、若要判断顶点vi到vj是否存在边,只需要测试顶点vi的边表中adjvex是否存在结点vj的下标j就行了。
  3、若求顶点的所有邻接点,其实就是对此顶点的边表进行遍历,得到的adjvex域对应的顶点就是邻接点。


  若是有向图,邻接表结构是类似的,比如下图中第一幅图的邻接表就是第二幅图。
  但要注意的是有向图由于有方向,我们是以顶点为弧尾来存储边表的,这样很容易就可以得到每个顶点的出度。

  但也有时为了便于确定顶点的入度或以顶点为弧头的弧,我们可以建立一个有向图的 逆邻接表,即对每个顶vi点都建立一个链接为vi为弧头的表。如下图第三幅图所示。

   其他存储方式还有:十字链表、邻接多重表、边集数组。有兴趣的请查阅其他相关资料。


3、图的遍历

   图的遍历是和树的遍历类似,我们希望从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程就叫做 图的遍历。通常有两种遍历次序方案深度优先遍历和广度优先遍历

  

3.1 深度优先遍历

   深度优先遍历(Depth-First-Search),也有称为深度优先搜索,简称为DFS

   深度优先遍历其实就是一个递归的过程,其实转换成如上图的右图后,就像是一棵树的前序遍历。
   它从图中某个顶点v出发,访问此顶点,然后从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到。

  

3.2 广度优先遍历

   广度优先遍历(Breadth-first-search),又称广度优先搜索,简称BFS类似树的层序遍历


   不过如果图顶点和边非常多,不能在短时间内遍历完成,遍历的目的是为了寻找合适的顶点,那么选择哪种遍历就要仔细斟酌了。
   深度优先更适合目标比较明确,以找到目标为主要目的的情况;而广度优先更适合在不断扩大遍历范围时找到相对最优解的情况

   对于深度和广度而言,已经不是简单的算法实现问题,完全可以上升到方法论的角度。你求学是博览群书,还是深钻细研;你旅游是走马观花、蜻蜓点水,还是下马看花、深度体验;你交友是四海之内皆兄弟,还是人生得一知己足矣……其实都无对错之分,只视不同人的理解而有了不同的诠释。

4、最小生成树

   假设你是电信的实施工程师,需要为一个镇的九个村庄架设通信网络做设计,村庄位置大致如下图,其中v0-v8是村庄,之间连线的数字表示村与村间的可通达的直线距离,比如v0至V1就是10公里(个别如v0与v6,v6与v8,v5与v7未测算距离是因为有高山或湖泊,不予考虑)。你们领导要求你必须用最小的成本完成这次任务。你会怎么办?

   一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边。那么我们把构造连通网的最小代价生成树称为 最小生成树

  经典的有两种算法普里姆算法和克鲁斯卡尔算法

4.1 普利姆算法(Prim)

  为了能讲明白这个算法,我们先构造如下图的邻接矩阵:

  1、程序开始运行,我们由第4-5行,创建了两个一维数组lowcostadjvex,长度都为顶点个数9。
  2、第6、7行我们分别给这两个数组的第一个下标位赋值为0,arjvex[0]=0其实意思就是我们现在从顶点v0开始(事实上,最小生成树从哪个顶点开始计算都无所谓,我们假定从v0开始),lowcost[0]=0就表示v0已经被纳人到最小生成树中,之后凡是lowcost数组中的值被设置为0就是表示此下标的顶点被纳人最小生成树。
  3、第8-12行表示我们读取邻接矩阵的第一行数据。将数值赋值给lowcost数组,所以此时lowcost数组值为 {0,10,65535,6553s65535,11,65535,65535,65535},而adjvex则全部为0。

  4、第13-36行,整个循环过程就是构造最小生成树的过程。
  5、第15-16行,将min设置为了一个极大值65535,它的目的是为了之后找到一定范围内的最小权值。j是用来做顶点下标循环的变量,k是用来存储最小权值的顶点下标。
  6、第17-25行,循环中不断修改min为当前lowcost数组中最小值,并用k保留此最小值的顶点下标。经过循环后,min=10k=1。注意19行if判断的lowcost[j]!=0表示已经是生成树的顶点不参与最小权值的查找。

  7、第26行,因k=1, adjvex[1]=0,所以打印结果为(0,1),表示v。至VI边为最小生成树的第一条边。如下图所示。

  8、第27行,此时因k=1我们将lowcost[k]=0就是说顶点V1纳人到最小生成树中。此时lowcost数组值为{0,0,65535,65535,65535,11,6553s,6s535,65535}

  9、第28-35行,j循环由1至8,因k=1,查找邻接矩阵的第V1行的各个权值,与lowcost的对应值比较,若更小则修改lowcost值,并将k值存入 adjvex数组中。因第V1行有18、16、12均比65535小,所以最终lowcost数组的值为:{0,0,18,65535,11,16,65535,12}adjvex数组的值为:{0,0,1,0,0,0,1,0,1}。这里第30行if判断的lowcost[j]!=0也说明v0和V1已经是生成树的顶点不参与最小权值的比对了。
  10、再次循环,由第15行到第26行,此时min=11k=5adjvex[5]=0。因此打印结果为(0,5)。表示v0至v5边为最小生成树的第二条边,如下图所示:

  11、接下来执行到36行,lowcost数组的值为:{0,0,18,65535,26,0,16,65535, 12}。adjvex数组的值为:{0,0,1,0,5,0,1,0,1}

  12、之后,可以自己去模拟。通过不断的转换,构造的过程如下图所示结果。

4.2 克鲁斯卡尔(kruskal)

  通俗点讲:克鲁斯卡尔主要是找图中最小权值的边,直至所有顶点相连,但是要注意:整个过程中不能形成回路!


  对比两个算法,克鲁斯卡尔算法主要是针对边来展开,边数少时效率会非常高,所以对于稀疏图有很大的优势;而普里姆算法对于稠密图,即边数非常多的情况会更好一些

5、最短路径

  现实中,每个人需求不同,选择方案就不尽相同。有人为了省钱,它需要的是路程最短(定价以路程长短为标准),但可能由于线路班次少,换乘站间距离长等原因并不省时间;而另一些人,为了要赶飞机火车或者早晨上班不迟到,他最大的需求是总时间要短;还有一类人,如老人行动不便,或者上班族下班,忙碌一天累得要死,他们都不想多走路,哪怕车子绕远路耗时长也无所谓,关键是换乘要少,这样可以在车上好好休息一下(有些线路方案换乘两次比换乘三四次耗时还长)。
  这些都是老百姓的需求,简单的图形可以靠人的经验和感觉,但复杂的道路或地铁网就需要计算机通过算法计算来提供最佳的方案。我们今天就要来研究关于图的最短路径的问题。

5.1 迪杰斯特拉(Dijkstra)算法

  大致明白,这个迪杰斯特拉(Dijkstra)算法是如何干活的了。
  它并不是一下子就求出了v0到v8的最短路径,而是一步步求出它们之间顶点的最短路径,过程中都是基于已经求出的最短路径的基础上,求得更远顶点的最短路径,最终得到你要的结果。

5.2 弗洛伊德(Floyd)算法

在这里插入图片描述

6、拓扑排序

  我们会把施工过程、生产流程、软件开发、教学安排等都当成一个项目工程来对待,所有的工程都可分为若干个“活动”的子工程。
  例如下图是非专业人士绘制的一张电影制作流程图,现实中可能并不完全相同,但基本表达了一个工程和若干个活动的概念。
  在这些活动之间,通常会受到一定的条件约束,如其中某些活动必须在另一些活动完成之后才能开始。就像电影制作不可能在人员到位进驻场地时,导演还没有找到,也不可能在拍摄过程中,场地都没有。这都会导致荒谬的结果。因此这样的工程图,一定是无环的有向图。

  在一个表示工程的有向图中,用顶点表示活动用弧表示活动之间的优先关系这样的有向图为顶点表示活动的网,我们称为AOV网。AOV网中的弧表示活动之间存在的某种制约关系。

  设G=(V,E)是一个具有n个顶点的有向图,V中的顶点序列v1,v2,…,vn,满足若从顶点vi到vj有一条路径,则在顶点序列中顶点vi必在顶点vj之前。则我们称这样的顶点序列为一个拓扑序列

  所谓拓扑排序,其实就是对一个有向图构造拓扑序列的过程。

  构造时会有两个结果,如果此网的全部顶点都被输出,则说明它是不存在环(回路)的AOV网
  如果输出顶点数少了,哪怕是少了一个,也说明这个网存在环(回路),不是AOV网

  一个不存在回路的AOV网,我们可以将它应用在各种各样的工程或项目的流程图中,满足各种应用场景的需要,所以实现拓扑排序的算法就很有价值了。

7、关键路径

  在前面讲了AOV网的基础上,我们来介绍一个新的概念
  在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网,我们称之为AOE网(Activity On Edge Network)。

  我们把AOE网中没有入边的顶点称为始点或源点,没有出边的顶点称为终点或汇点。由于一个工程,总有一个开始,一个结束,所以正常情况下,AOE网只有一个源点一个汇点

  如下图就是一个AOE网。其中V0即是源点,v0表示一个工程的开始,V9是汇点,表示整个工程的结束,顶点v0,v1,…,v9分别表示事件。弧<v0,v1>,<V0, V2>…都表示一个活动,用a0,a1,…,a12表示,它们的值代表着活动持续的时间,比如弧<v0,v1>就是从源点开始的第一个活动 a0,它的时间是3个单位。

  我们把路径上各个活动所持续的时间之和称为路径长度从源点到汇点具有最大长度的路径叫关键路径,在关键路径上的活动叫关键活动

  案例:

  假设一个学生放学回家,除掉吃饭、洗漱外,到睡觉前有四小时空闲,而家庭作业需要两小时完成。
  不同的学生会有不同的做法,抓紧的学生,会在头两小时就完成作业,然后看看电视、读读课外书什么的;但也有超过一半的学生会在最后两小时才去做作业,要不是因为没时间,可能还要再拖延下去。
  这里做家庭作业这一活动的最早开始时间是四小时的开始,可理解为0,而最晚开始时间是两小时之后马上开始,不可以再晚,否则就是延迟了,此时可以理解为 2。显然,当最早和最晚开始时间不相等时就意味着有空闲
  接着,你老妈发现了你拖延的小秘密,于是买了很多的课外习题,要求你四个小时,不许有一丝空闲,省得你拖延或偷懒。此时整个四小时全部被占满,最早开始时间和最晚开始时间都是0,因此它就是关键活动了

  也就是说,我们只需要找到所有活动的最早开始时间和最晚开始时间,并且比较它们,如果相等就意味着此活动是关键活动,活动间的路径为关键路径。如果不等,则就不是。

  为此,定义如下几个参数。
  1、事件的最早发生时间etv:即顶点的最早发生时间;
  2、事件的最晚发生时间ltv:即顶点Vk的最晚发生时间,也就是每个顶点对应的事件最晚需要开始的时间,超出此时间将会延误整个工期;
  3、活动的最早开工时间ete :即弧ak的最早发生时间。
  4、活动的最晚开工时间Ite:即弧ak的最晚发生时间,也就是不推迟工期的最晚开工时间。

  上图中的结果:

  关键路径为:v0–>v2–>v3–>v4–>v7–>v8–>v9
  关键活动为:a1、a4、a6、a8、a11、a12

  关键路径不一定唯一。

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

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

相关文章

Sentinel限流-@SentinelResource注解配置

SentinelResource 配置-上 &#xff08;按资源名配置限流规则&#xff09; 1&#xff09; Sentinel 控制台配置流控规则&#xff1a; 2&#xff09;java 代码&#xff1a; GetMapping("/byResource")SentinelResource(value "byResource", blockHandler …

Django项目——通过APIView实现API访问

前提 该文章在已有项目的基础上进行修改 https://blog.csdn.net/qq_38122800/article/details/128583379?spm1001.2014.3001.5502 1、配置序列化器 序列化器包含序列化和反序列化两个过程,简单点理解就是 序列化 : 将从数据库中查的数据变为前端页面可以接受的json数据 反…

Odoo 16 企业版手册 - 库存管理之重订货规则

重订货规则 在Odoo 库存模块中&#xff0c;您可以配置一组规则&#xff0c;帮助您确保库存永远不会用完。Odoo将尝试使用重订货规则在您的库存中保持至少最低数量的产品。让我们看看此功能在Odoo 16中是如何工作的。为此&#xff0c;您可以从库存模块中选择一个可存储的产品。 …

qt学习记录

一、新建项目时只有pro文件而没有其他文件 此时需要在Kits界面将所有编译器选择&#xff0c;即可出现其他文件 二、QMainWindow、QWidget、QDialog的区别 ①QWidget继承于QObject和QPaintDevice&#xff0c;QDialog和QMainWindow则继承于QWidget&#xff0c;QDialog、QMainWi…

[ 数据结构 ] 弗洛伊德算法(Floyd)--------最短路径问题

0 Floyd算法介绍 和 Dijkstra 算法一样&#xff0c;弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的算法。该算法名称以创始人之一、1978 年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特弗洛伊德命名弗洛伊德算法(Floyd)计算图中各个顶点之间的最短路…

新应用——信息化财务管理,一站式满足多个需求

财务管理应用是企业为了适应当下社会环境提出的一种将财务管理进行信息化管理的方法&#xff0c;与传统财务管理模式不同&#xff0c;将各类业务数据编制为电子数据&#xff0c;便于财务人员查找数据内容&#xff0c;可以更高效的开展工作。百数应用中心的财务管理应用涵盖了项…

机器学习笔记之深度信念网络(二)模型构建思想(RBM叠加结构)

机器学习笔记之深度信念网络——模型构建思想引言回顾&#xff1a;深度信念网络的结构表示解析RBM隐变量的先验概率通过模型学习隐变量的先验概率引言 上一节介绍了深度信念网络的模型表示&#xff0c;本节将介绍深度信念网络的模型构建思想——受限玻尔兹曼机叠加结构的基本逻…

Flutter多分支打包持续化集成

一、使用效果演示 1.1、选择参数打包 以下为参数使用说明。 packingType枚举 android、ios android ios android&ios (新功能&#xff1a;并行打包)备注&#xff1a; android、ios&#xff1a;串行打包&#xff0c;即先打一个再打一个 android&ios&#xff1a;为并行…

与香港财政司司长同台,欧科云链在这场峰会上都说了啥?

今天&#xff0c;POWER 2023香港Web3创新者峰会在中国香港如期召开&#xff0c;香港特别行政区政府财政司司长陈茂波、财经事务及库务局副局长陈浩濂、全国政协委员、立法会议员吴杰庄等港府要员出席峰会。 作为本场峰会的受邀企业&#xff0c;欧科云链控股(01499.HK)公司执行董…

Kernel Pwn基础教程之 Double Fetch

一、前言 Double Fetch是一种条件竞争类型的漏洞&#xff0c;其主要形成的原因是由于用户态与内核态之间的数据在进行交互时存在时间差&#xff0c;我们在先前的学习中有了解到内核在从用户态中获取数据时会使用函数copy_from_user&#xff0c;而如果要拷贝的数据过于复杂的话…

人工智能-正则表达式

目录1、正则表达式概述2、re模块3、匹配单个字符4、匹配多个字符5、匹配开头和结尾6、匹配分组7、总结1、正则表达式概述 在实际开发过程中经常会需要查找某些复杂字符串的格式 正则表达式&#xff1a;记录文本规则的代码 正则表达式特点&#xff1a; 语法令人头疼&#xff…

立创eda专业版学习笔记(4)(隐藏铺铜)

这里的隐藏有两个意思&#xff0c;一个是铺铜过后把铺铜的填充区域隐藏&#xff0c;方便看图&#xff0c;另外一个是隐藏铺铜的轮廓&#xff0c;方便后续改进。 第一种隐藏&#xff0c;隐藏铺铜的填充区域&#xff08;成片的图块&#xff09;&#xff0c;但是保留轮廓线 这是全…

联想LJ2655DN激光打印机清零方法

联想LJ2655DN激光打印机是市面上常见的打印机,为了节约成本,我们一般使用都是代用硒鼓来代替原装硒鼓,但是发现更换完硒鼓以后还是不能打印甚至有的机器能够打印但是打印速度会变慢或很慢,这个时候这就需要我们对打印机进行清零复位操作了,此款机器因用户更换的硒鼓类型不…

C++ 模板进阶

目录 1. 非类型模板参数 2. 模板的特化 2.1 概念 2.2 函数模板特化 2.3 类模板特化 2.3.1 全特化 2.3.2 偏特化 2.3.3 类模板特化应用示例 3. 模板总结 1. 非类型模板参数 我们在C语言中使用数组的时候可以定义静态数组&#xff0c;但是有个缺陷就是编译器在对越界检查…

Java自定义泛型类注意点

目录 自定义泛型类 如果定义了泛型类&#xff0c;实例化没有指明类的泛型&#xff0c;则认为此泛型类型为Object类型 由于子类在继承带泛型的父类时&#xff0c;指明了泛型类型。则实例化子类对象时&#xff0c;不需要指明类型 由于子类在继承带泛型的父类时&#xff0c;没有…

WebDAV之葫芦儿·派盘 + Photosync

PhotoSync 支持WebDAV方式连接葫芦儿派盘。 苹果手机通过无线传输,备份和共享照片/视频到计算机,其他手机,NAS和流行的云和照片服务的最佳解决办法,快来试下PhotoSync同步工具吧。 PhotoSync面向移动设备

安装部署wordpress(Ubuntu)

wordpress是一个目前流行的基于web的内容管理系统软件。它是基于PHP语言和MySQL数据库开发的&#xff0c;用户可以在支持 PHP 和 MySQL数据库的服务器上快速轻松的部署自己的网站&#xff08;博客&#xff0c;外贸网站等等&#xff09;。WordPress有非常多的第三方开发的免费模…

产线工控安全之现状分析及方案应对

产线安全现状 工业控制系统是支撑国民经济的重要设施&#xff0c;是工业领域的神经中枢。现在工业控制系统已经广泛应用于电力、通信、化工、交通、航天等工业领域&#xff0c;支撑起国计民生的关键基础设施。 随着传统的工业转型&#xff0c;数字化、网络化和智能化的工业控…

数学建模---数值微积分

目录 一.引言 二.数值微分 1.数值差分与差商 利用matlab观察差分与差商的区别&#xff1a; 例题&#xff1a; 二.数值积分 1.数值积分基本定理 2.常见的数值积分公式&#xff1a; 积分公式的精度&#xff1a; 3.数值积分的matlab实现 一.引言 在科学研究和工程计算中&…

LINUX提权之环境变量提权篇

前言 上一篇文章给大家介绍了linux中的内核提权的一些知识点不知道大家学的怎么样了&#xff0c;今天给大家带来一个全新的提权方法——“环境变量提权”,本文会介绍关于环境变量提权的基本知识以及利用方法。 环境变量提权 PATH是Linux系统中的环境变量&#xff0c;指定存储…