资源描述
第七章 图图的基本概念n图n由顶点(Vertex)集合及顶点间的关系(即边,Edge)集合组成的一种数据结构:Graph( V, E ) nV = x | x 某个数据对象 顶点的有穷非空集合;nE1 = (x, y) | x, y V E1是顶点之间关系的有穷集合,也叫做边(Edge)集合,此时的图称为无向图。 n或E2 = | x, y V & Path (x, y) E2 表示从 x 到 y 的一条弧(Arc),且称x为弧尾,y为弧头,这样的图称为有向图。n有向图与无向图n在有向图中,顶点对 是有序的。n在无向图中,顶点对(x, y)是无序的。n完全图n若有 n 个顶点的无向图有 n(n-1)/2 条边, 则此图为无向完全图。n若有 n 个顶点的有向图有n(n-1) 条边, 则此图为有向完全图00001111222265433无向完全图无向完全图无向图无向图有向图有向图有向完全图有向完全图n邻接顶点n如果 (u, v) 是 E(G) 中的一条边,则称 u 与 v 互为邻接顶点。n子图n设有两个图 G(V, E) 和 G(V, E)。若 V V 且 EE, 则称 图G 是 图G 的子图。0123子图子图0130123023n权n某些图的边具有与它相关的数, 称之为权。n这种带权图叫做网络(Network)。n顶点的度(Degree) n一个顶点v的度是与它相关联的边的条数。记作TD(v)。n在有向图中, 顶点的度等于该顶点的入度与出度之和。n顶点 v 的入度是以 v 为终点(弧头)的有向边的条数, 记作 ID(v); n顶点 v 的出度是以 v 为始点(弧尾)的有向边的条数, 记作 OD(v)。n顶点的度(TD)=出度(OD)+入度(ID)nTD(B) =OD(B)+ID(B) =1+2 =3ABECFn路径n在图 G(V, E) 中, 若从顶点 vi 出发, 沿一些边经过一些顶点 vp1, vp2, , vpm,到达顶点vj。则称顶点序列 (vi vp1 vp2 . vpm vj) 为从顶点vi 到顶点 vj 的路径。n它经过的边(vi, vp1)、(vp1, vp2)、.、(vpm, vj) 应是属于E的边。n路径长度n非带权图的路径长度是指此路径上边的条数。n带权图的路径长度是指路径上各边的权之和。n简单路径n若路径上各顶点 v1,v2,.,vm 均不 互相重复, 则称这样的路径为简单路径。n回路n若路径上第一个顶点 v1 与最后一个顶点vm 重合, 则称这样的路径为回路或环。n简单回路n若回路上各顶点 v1,v2,.,vm 均不 互相重复, 则称这样的回路为简单回路。012301230132n连通图与连通分量n在无向图中, 若从顶点v1到顶点v2有路径, 则称顶点v1与v2是连通的。如果图中任意一对顶点都是连通的, 则称此图是连通图。n非连通图的极大连通子图叫做连通分量。n强连通图与强连通分量 n在有向图中, 若对于每一对顶点vi和vj, 都存在一条从vi到vj和从vj到vi的路径, 则称此图是强连通图。n非强连通图的极大强连通子图叫做强连通分量。ACDEIBFOGHJNMLK非连通无向图的三个连通分量非连通无向图的三个连通分量BACDFEABECF有向图有向图强连通图强连通图无向图无向图连通图连通图n生成树n假设一个连通图的n个顶点和n-1条边构成一个极小连通子图,称该极小连通子图为此连通图的生成树。n在极小连通子图中增加一条边,则一定有环。n在极小连通子图中去掉一条边,则成为非连通图n注意:有n个顶点,n-1条边的图不一定是生成树BACDFEBACDFEn生成森林n对非连通图,称由各个连通分量的生成树的集合为此非连通图的生成森林图的存储结构n1、邻接矩阵(数组)表示法n有一个记录各个顶点信息的顶点表,n还有一个表示各个顶点之间关系的邻接矩阵。n设图 A = (V, E)是一个有 n 个顶点的图, 图的邻接矩阵是一个二维数组 A.Edgenn,定义:n无向图的邻接矩阵是对称的;01230101101001011010A.edge012000101010A.edgen在有向图中n统计第 i 行 1 的个数可得顶点 i 的出度,n统计第 j 列 1 的个数可得顶点 j 的入度。n在无向图中,n统计第 i 行 (或列) 1 的个数可得顶点i 的度。n网络的邻接矩阵186329542031068053290410A.edgen用邻接矩阵表示的结构定义const int NumVertices = 10; /顶点个数typedef char VertexData; /顶点数据类型 typedef int EdgeData; /边上权值类型typedef struct VertexData vexListNumVertices; /顶点表 EdgeData EdgeNumVerticesNumVertices; /邻接矩阵, 可视为边之间的关系 int n, e; /图中当前的顶点个数与边数 MTGraph;n2、邻接表 表示法n邻接表:是图的一种链式存储结构。n顶点的结点结构ndata; / 顶点信息nfirstarc; /指针,指向第一条依附该顶点的弧n弧的结点结构nadjvex; / 该弧所指向的顶点的位置nnextarc;/指针,指向下一条弧ninfo; / 该弧相关信息,如:权adjvex nextarc info data firstarcn无向图的邻接表n同一个顶点发出的边链接在同一个边链表中,每一个链结点代表一条边(边结点), 结点中有另一顶点的下标 dest 和指针 link。ABCDdata adjABCD0123dest linkdest link 130210n有向图的邻接表和逆邻接表dest linkABCABC012dest link 邻接表邻接表 (出边表出边表)102 data adjABC012dest link逆邻接表逆邻接表 (入边表入边表) 011data adjn网络 (带权图) 的邻接表BACD69528data adjABCD0123dest cost link 1 53 62 83 21 9(出边表出边表)(顶点表顶点表)n带权图的边结点中保存该边上的权值 cost。n顶点 i 的边链表的表头指针 adj 在顶点表的下标为 i 的顶点记录中,该记录还保存了该顶点的其它信息。n在邻接表的边链表中,各个边结点的链入顺序任意,视边结点输入次序而定。n设图中有 n 个顶点,e 条边,则用邻接表表示无向图时,需要 n 个顶点结点,2e 个边结点;用邻接表表示有向图时,若不考虑逆邻接表,只需 n 个顶点结点,e 个边结点。n邻接表表示的图的定义typedef char VertexData; /顶点数据类型typedef int EdgeData; /边上权值类型typedef struct node /边结点 int dest; /目标顶点下标 EdgeData cost; /边上的权值 struct node * next; /下一边链接指针 EdgeNode;typedef struct /顶点结点 VertexData data; /顶点数据域 EdgeNode * firstAdj; /边链表头指针 VertexNode;typedef struct /图的邻接表 VertexNode VexList NumVertices; /邻接表 int n, e; /图中当前的顶点个数与边数 AdjGraph;n邻接表的构造算法(无向图)void CreateGraph (AdjGraph G) cin G.n G.e; /输入顶点个数和边数 for ( int i = 0; i G.VexListi.data; /输入顶点信息 G.VexListi.firstAdj = NULL; for ( i = 0; i tail head weight; EdgeNode * p = new EdgeNode; p-dest = head; p-cost = weight; /链入第 tail 号链表的前端 p-link = G.VexListtail.firstAdj; G.VexListtail.firstAdj = p; p = new EdgeNode; p-dest = tail; p-cost = weight; /链入第 head 号链表的前端 p-link = G.VexListhead.firstAdj; G.VexListhead.firstAdj = p; 图的遍历n从图中某一顶点出发访遍图中所有的顶点,且使每个顶点仅被访问一次,这一过程就叫做图的遍历 (Traversing Graph)。n图中可能存在回路,且图的任一顶点都可能与其它顶点相通,在访问完某个顶点之后可能会沿着某些边又回到了曾经访问过的顶点。n为了避免重复访问,可设置一个标记顶点是否被访问过的辅助数组 visited 0.n-1。n辅助数组 visited 的初始状态为 0, 在图的遍历过程中, 一旦某一个顶点 i 被访问, 就立即让 visited i 为 1, 防止它被多次访问。n两种图的遍历方法:n深度优先搜索DFS (Depth First Search)n广度优先搜索BFS (Breadth First Search)n遍历结果与具体存储相关n深度优先搜索DFSn深度优先搜索过程67ACDEGBFIHACDEGBFIH1234589123456789深度优先生成树深度优先生成树前进回退n访问图中某一起始顶点 v 后, n由 v 出发, 访问它的任一邻接顶点 w1; 再从 w1 出发,访问与 w1邻 接但还没有访问过的顶点 w2; 然后再从 w2 出发, 进行类似的访问, n如此进行下去, 直至到达所有的邻接顶点都被访问过的顶点 u 为止。n接着, 退回一步, 退到前一次刚访问过的顶点, 看是否还有其它没有被访问的邻接顶点。n如果有, 则访问此顶点, 之后再从此顶点出发, 进行与前述类似的访问; n如果没有, 就再退回一步进行搜索。n重复上述过程, 直到连通图中所有顶点都被访问过为止。n图的深度优先搜索算法void Graph_Traverse (AdjGraph G) int * visited = new int G.n; for ( int i = 0; i G.n; i+ ) visited i = 0; /访问数组 visited 初始化 for ( int i = 0; i G.n; i+ ) /可有多个连通分量 if ( ! visitedi ) DFS (G, i, visited ); /从顶点 i 出发开始搜索 delete visited; /释放 visited void DFS (AdjGraph G, int v, int visited ) cout GetValue (G, v) ; /访问顶点 v visitedv = 1; /顶点 v 作访问标记 int w = GetFirstNeighbor (G, v); /取 v 的第一个邻接顶点 w while ( w != -1 ) /若邻接顶点 w 存在 if ( !visitedw ) DFS (G, w, visited ); /若顶点 w 未访问过, 从w开始搜,递归 w = GetNextNeighbor (G, v, w ); /取顶点 v 排在 w 后的下一个邻接顶点 n广度优先搜索BFSn广度优先搜索过程ACDEGBFIHACDEGBFH123456789123456789广度优先生成树广度优先生成树In访问了起始顶点 v 之后, n由 v 出发, 依次访问 v 的各个未被访问过的邻接顶点 w1, w2, , wt, n然后再顺序访问 w1, w2, , wt 的所有还未被访问过的邻接顶点。n再从这些访问过的顶点出发,再访问它们的所有还未被访问过的邻接顶点, n如此做下去,直到图中所有顶点都被访问到为止。n广度优先搜索类似于树的层序遍历n广度优先搜索是一种分层的搜索过程, 每向前走一步可能访问一批顶点, 不像深度优先搜索那样有往回退的情况。因此, 广度优先搜索不是一个递归的过程。n为了实现逐层访问, 算法中使用了一个队列,以记忆正在访问的这一层和下一层的顶点,以便于向下一层访问。n为避免重复访问, 需要一个辅助数组 visitedn,给被访问过的顶点加标记。n图的广度优先搜索算法void Graph_Traverse (AdjGraph G) int * visited = new int G.n; for ( int i = 0; i G.n; i+ ) visited i = 0; /访问数组 visited 初始化 for ( int i = 0; i G.n; i+ ) if ( ! visitedi ) BFS (G, i, visited ); /从顶点 i 出发开始搜索 delete visited; /释放 visited void BFS (AdjGraph G, int v, int visited ) cout GetValue (v) ; visitedv = 1; Queue q; InitQueue(&q); EnQueue (&q, v); /进队列 while ( ! QueueEmpty (&q) ) /队空搜索结束 DeQueue (&q, v); int w = GetFirstNeighbor (G, v); while ( w != -1 ) /若邻接顶点 w 存在 if ( !visitedw ) /未访问过 cout GetValue (w) ; visitedw = 1; EnQueue (&q, w); w = GetNextNeighbor (G, v, w); /重复检测 v 的所有邻接顶点 /外层循环,判队列空否 / BFS图的连通性问题n连通分量n当无向图为非连通图时, 从图中某一顶点出发, 利用深度优先搜索算法或广度优先搜索算法不可能遍历到图中的所有顶点, 只能访问到该顶点所在的最大连通子图(即:连通分量)的所有顶点。n若从无向图的每一个连通分量中的一个顶点出发进行遍历, 可求得无向图的所有连通分量。n求连通分量的算法需要对图的每一个顶点进行检测:n若已被访问过,则该顶点一定是落在图中已求得的连通分量上;n若还未被访问,则从该顶点出发遍历图,可求得图的另一个连通分量。n对于非连通的无向图,所有连通分量的生成树组成了非连通图的生成森林。ACDEIBFOGHJNMLK非连通无向图的三个连通分量非连通无向图的三个连通分量AHKCDEIBFOGJNML非连通图的连通分量的极小连通子图非连通图的连通分量的极小连通子图(生成树生成树)n生成树n用不同的遍历图的方法,可以得到不同的生成树;n从不同的顶点出发,也可能得到不同的生成树。nn 个顶点的连通网络的生成树有 n 个顶点和n-1 条边。n最小生成树n使用且仅使用该网络中的n-1 条边来联结网络中的 n 个顶点;n各边上的权值的总和达到最小。n普里姆Prim算法n用于构造最小生成树n基本思想:n从连通网络 N = V, E 中的某一顶点 u0 出发, 选择与它关联的具有最小权值的边 ( u0, v ), 将其顶点加入到生成树顶点集合U中。n以后每一步从一个顶点在 U 中,而另一个顶点不在 U 中的各条边中选择权值最小的边(u, v), 把它的顶点加入到集合 U 中。如此继续下去, 直到网络中的所有顶点都加入到生成树顶点集合 U 中为止。n采用邻接矩阵作为图的存储表示。252510504613228102514242216185046132504613210原图原图 (1) (2)504613210(3) (4) (5) (6)50461321022125046121025142216123252212n在构造过程中,还设置了两个辅助数组:nlowcosti 存放生成树顶点集合内内顶点到生成树外外顶点i的各边的当前最小权值;nnearvexi 记录生成树顶点集合内内哪个顶点距离集合外外顶点i最近。n例子02418140251024250221822012120161416028102805046132102514241618122822n若选择从顶点0出发,即u0 = 0,则两个辅助数组的初始状态为:n然后反复做以下工作:n在 lowcost 中选择 nearvexi -1 & lowcosti最小的边, 用 v 标记它。则选中的权值最小的边为(nearvexv, v), 相应的权值为 lowcostv。n将 nearvexv 改为-1, 表示它已加入生成树顶点集合。0 28 10 - -1 0 0 0 0 0 0 lowcostnearvex0 1 2 3 4 5 6n将边 (nearvexv, v, lowcostv ) 加入生成树的边集合。n取 lowcosti = min lowcosti, Edgevi ,即用生成树顶点集合外各顶点 i 到刚加入该集合的新顶点 v 的距离 Edgevi 与原来它们到生成树顶点集合中顶点的最短距离lowcosti 做比较, 取距离近的作为这些集合外顶点到生成树顶点集合内顶点的最短距离。n如果生成树顶点集合外顶点 i 到刚加入该集合的新顶点 v 的距离比原来它到生成树顶点集合中顶点的最短距离还要近,则修改nearvexi : nearvexi = v。表示生成树外顶点i到生成树内顶点v当前距离最近。0 28 10 - -1 0 0 0 0 0 0 lowcostnearvex0 1 2 3 4 5 6选选 v=5选边选边 (0,5)0241814025102425022182201212016141602810280504613210251424161812282250461322810251424221618原图 边 (0,5,10) 加入生成树1204613210255顶点顶点v=5加入生成树顶点集合:加入生成树顶点集合:0 28 25 10 - -1 0 0 0 5 - -1 0 lowcostnearvex0 1 2 3 4 5 6选选 v=4选边选边 (5,4)0 1 2 3 4 5 6顶点顶点v=4加入生成树顶点集合:加入生成树顶点集合:0 28 22 25 10 24 - -1 0 0 4 - -1 - -1 4 lowcostnearvex选选 v=3选边选边 (4,3)50461322810251424221618原图 边 (5,4,25) 加入生成树125046132102522顶点顶点v=3加入生成树顶点集合:加入生成树顶点集合:0 28 12 22 25 10 18 - -1 0 3 - -1 - -1 - -1 3 lowcostnearvex0 1 2 3 4 5 6选选 v=2选边选边 (3,2)50461322810251424221618原图 边 (4,3,22) 加入生成树12504613210252212lowcostnearvex0 1 2 3 4 5 6顶点顶点v=2加入生成树顶点集合:加入生成树顶点集合:0 16 12 22 25 10 18 - -1 2 - -1 - -1 - -1 - -1 3 选选 v=1选边选边 (2,1)50461322810251424221618原图 边 (3,2,12) 加入生成树125041321025221612顶点顶点v=1加入生成树顶点集合:加入生成树顶点集合:0 16 12 22 25 10 14 - -1 - -1 - -1 - -1 - -1 - -1 1 lowcostnearvex0 1 2 3 4 5 6选选 v=6选边选边 (1,6)50461322810251424221618原图 边 (2,1,16) 加入生成树125046132102514221612lowcostnearvex0 1 2 3 4 5 6顶点顶点v=6加入生成树顶点集合:加入生成树顶点集合:0 16 12 22 25 10 14 - -1 - -1 - -1 - -1 - -1 - -1 - -1 50461322810251424221618原图 边 (1,6,14) 加入生成树125046132102514221612n最后生成树中边集合里存入得各条边为:n(0, 5, 10), (5, 4, 25), (4, 3, 22), (3, 2, 12), (2, 1, 16), (1, 6, 14)n注意:当各边有相同权值时,由于选择的随意性,产生的生成树可能不唯一。当各边的权值不相同时,产生的生成树是唯一的2250461321025141612nPrim算法实现最短路径n最短路径问题:n如果从图中某一顶点(称为源点)到达另一顶点(称为终点)的路径可能不止一条,如何找到一条路径使得沿此路径上各边上的权值总和达到最小。n问题解法n边上权值非负情形的单源最短路径问题 Dijkstra算法n边上权值为任意值的单源最短路径问题 Bellman和Ford算法n任意顶点之间的最短路径 Floyd算法n边上权值非负情形的单源最短路径问题n问题的提法: 给定一个带权有向图D与源点 v,求从 v 到D中其它顶点的最短路径。限定各边上的权值大于或等于0。n为求得这些最短路径, Dijkstra提出按路径长度的递增次序, 逐步产生最短路径的算法。n首先求出长度最短的一条最短路径,再参照它求出长度次短的一条最短路径,依次类推,直到从顶点v到其它各顶点的最短路径全部求出为止。10432101003050206010v1 (v0v1)10v2 (v0v1v2)60 (v0v3v2)50 v3 (v0v3)30 (v0v3) 30v4 (v0v4)100 (v0v4)100 (v0v3v4)90 (v0v3v2 v4)60 S v0,v1 v0,v1,v3 v0,v1,v3,v2 v0,v1,v3,v5,v4第第1 1步步 第第2 2步步 第第3 3步步 第第4 4步步n引入辅助数组dist。它的每一个分量disti表示当前找到的从源点 v0到终点 vi 的最短路径的长度。初始状态:n若从源点v0到顶点 vi 有边, 则disti为该边上的权值;n若从源点v0到顶点 vi 无边, 则disti为 。n设 S 是已求得的最短路径的终点的集合,可证:n下一条最短路径必然是从v0 出发,中间只经过 S 中的顶点便可到达的那些顶点vx (vxVS )的路径中的一条。n每次求得一条最短路径后, 其终点vk 加入集合S,然后对所有的vi VS,修改其 disti值。nDijkstra算法n 初始化: S v0 ; distj Edge0j, j = 1, 2, , n-1; / n为图中顶点个数n 求出最短路径的长度: distk min disti , i V- S ; S S U k ; /顶点k加入集合Sn 修改: disti min disti, distk +Edgeki , 对每一个 i V- S, k S ; n 判断:若 S = V, 则算法结束,否则转 。10432101003050206010 06002010050010030100432100 10 30 100dist0 1 2 3 4S: v00 10 60 30 100distS: v0,v10 10 50 30 90distS: v0,v1,v30 10 50 30 90distS: v0,v1,v3,v2有向无环图及其应用n一个无环的有向图称为有向无环图DAG (Directed Acycline Graph)n可用于描述含有公共子式的表达式n可用于描述一项工程或系统的进行过程n对于一个工程,我们关心:n工程能否顺利完成拓扑排序问题n估算整个工程完成所必须的最短时间关键路径问题拓扑排序n计划、施工过程、生产流程、程序流程等都是“工程”。除了很小的工程外,一般都把工程分为若干个叫做“活动”的子工程。完成了这些活动,这个工程就可以完成了。n例如,计算机专业学生的学习就是一个工程,每一门课程的学习就是整个工程的一些活动。其中有些课程要求先修课程,有些则不要求。这样在有的课程之间有先后关系,有的课程可以并行地学习。 C1 高等数学高等数学 C2 程序设计基础程序设计基础 C3 离散数学离散数学 C1, C2 C4 数据结构数据结构 C3, C2 C5 高级语言程序设计高级语言程序设计 C2 C6 编译方法编译方法 C5, C4 C7 操作系统操作系统 C4, C9 C8 普通物理普通物理 C1 C9 计算机原理计算机原理 C8 课程代号课程代号 课程名称课程名称 先修课程先修课程学生课程学习工程图学生课程学习工程图C8C3C5C4C9C6C7C1C2n可以用有向图表示一个工程。在这种有向图中,用顶点表示活动,用有向边表示活动Vi 必须先于活动Vj 进行。这种有向图叫做顶点表示活动的AOV网络 (Activity On Vertices)。 n在AOV网络中不能出现有向回路, 即有向环。如果出现了有向环,则意味着某项活动应以自己作为先决条件。n因此,对给定的AOV网络,必须先判断它是否存在有向环。n检测有向环的一种方法是对AOV网络构造它的拓扑有序序列。n即将各个顶点 (代表各个活动)排列成一个线性有序的序列,使得AOV网络中所有应存在的前驱和后继关系都能得到满足。 n这种构造AOV网络全部顶点的拓扑有序序列的运算就叫做拓扑排序。n如果通过拓扑排序能将AOV网络的所有顶点都排入一个拓扑有序的序列中, 则该网络中必定不会出现有向环。n如果AOV网络中存在有向环,此AOV网络所代表的工程是不可行的。n例如, 对学生选课工程图进行拓扑排序, 得到的拓扑有序序列为 C1 , C2 , C3 , C4 , C5 , C6 , C8 , C9 , C7或 C1 , C8 , C9 , C2 , C5 , C3 , C4 , C7 , C6C8C3C5C4C9C6C7C1C2n拓扑排序的方法n 输入AOV网络。令 n 为顶点个数。n 在AOV网络中选一个没有直接前驱的顶点, 并输出之; n 从图中删去该顶点, 同时删去所有它发出的有向边;n 重复以上 、步, 直到n全部顶点均已输出,拓扑有序序列形成,拓扑排序完成;或者:n图中还有未输出的顶点, 但已跳出处理循环。说明图中还剩下一些顶点, 它们都有直接前驱。这时网络中必存在有向环。C0C1C2C3C4C5拓扑排序的过程拓扑排序的过程(a) 有向无环图有向无环图C2C5C1C0C3(b) 输出顶点输出顶点C4C1C2C5C3(c) 输出顶点输出顶点C0C4C0C2C5C1C3(d) 输出顶点输出顶点C3C1C2C5(e) 输出顶点输出顶点C2C5C1(f) 输出顶点输出顶点C1C5(g) 输出顶点输出顶点C5(h) 拓扑排序完成拓扑排序完成n最后得到的拓扑有序序列为 C4 , C0 , C3 , C2 , C1 , C5 。它满足图中给出的所有前驱和后继关系,对于本来没有这种关系的顶点,如C4和C2,也排出了先后次序关系。AOV网络及其邻接表表示网络及其邻接表表示C0C1C2C3C4C5 C0 C1 C2 C3 C4 C5 012345countID data adj 130103 1 dest link 3 0 5 1 5 0 0 1 5 0n在邻接表中增设一个数组countID ,记录各顶点入度。n入度为零的顶点即无前驱顶点。n在输入数据前, 顶点表VexList 和入度数组countID 全部初始化。n在输入数据时, 每输入一条边, 就需要建立一个边结点, 并将它链入相应边链表中, 统计入度信息。n在算法中, 使用一个存放入度为零的顶点的链式栈, 供选择和输出无前驱的顶点。n拓扑排序算法:n1、扫描顶点表,将入度为0 的顶点入栈;n2、while ( 栈非空 ) 将栈顶顶点v弹出并输出之; 检查v的出边,将每条出边终点u的入度减1, 若u的入度变为0,则把u推入栈; n3、若输出的顶点数小于n,则输出“有回路”;否则拓扑排序正常结束。关键路径n如果在无有向环的带权有向图中, 用有向边表示一个工程中的活动, 用边上权值表示活动持续时间, 用顶点表示事件(状态), 则这样的有向图叫做用边表示活动的网络, 简称 AOE ( Activity On Edges ) 网络。a9=61324a1=8a2=125678a10=12a8=18a5=28a6=8a7=6a3=14a4=10nAOE网络在某些工程估算方面非常有用。例如,可以使人们了解:n完成整个工程至少需要多少时间(假设网络中没有环)?n为缩短完成工程所需时间, 应加快哪些活动?n从源点到各个顶点, 以至从源点到汇点的有向路径可能不止一条。这些路径的长度也可能不同。n完成不同路径的活动所需的时间虽然不同, 但只有各条路径上所有活动都完成了, 整个工程才算完成。n因此, 完成整个工程所需的时间取决于从源点到汇点的最长路径长度, 即在这条路径上所有活动的持续时间之和。这条路径长度最长的路径就叫做关键路径(Critical Path)。n要找出关键路径,必须找出关键活动:即不按期完成就会影响整个工程完成的活动。n关键路径上的所有活动都是关键活动。因此, 只要找到了关键活动, 就可以找到关键路径。n定义几个与计算关键活动有关的量:n 事件Vi 的最早可能开始时间Vein是从源点V0 到顶点Vi 的最长路径长度。n 事件Vi 的最迟允许开始时间Vlin是在保证汇点Vn-1 在Ven-1 时刻完成的前提下,事件Vi 的允许的最迟开始时间。n 活动ak 的最早可能开始时间 ekn设活动ak 在边上, 则ek是从源点V0到顶点Vi 的最长路径长度。因此, ek = Vei。n 活动ak 的最迟允许开始时间lknlk是在不会引起时间延误的前提下, 该活动允许的最迟开始时间。 lk = Vlj - dur() 其中, dur()是完成 ak 所需的时间。n 时间余量 lk - ekn表示活动 ak 的最早可能开始时间和最迟允许开始时间的时间余量。lk = ek 表示活动 ak 是没有时间余量的关键活动。n为找出关键活动, 需要求各个活动的 ek 与 lk,以判别是否 lk = ek。n为求得 ek与 lk, 需要先求得从源点 V0 到各个顶点 Vi 的 Vei 和 Vli。n求Vei的递推公式n 从 Ve0 = 0 开始,向前递推 S2, i = 1, 2, , n-1S2是所有指向Vi的有向边的集合。n 从Vln-1 = Ven-1开始,反向递推 S1, i = n-2, n-3, , 0S1是所有源自Vi的有向边的集合。n这两个递推公式的计算必须分别在拓扑有序及逆拓扑有序的前提下进行。 , ) ,( ijjVVdurjVemaxiVe, ) ,( jijVVdurjVlminiVln设活动ak(k=1,2,e)在带权有向边 上, 其持续时间用dur()表示, 则有ek = Vei;lk = Vlj - dur();k = 1, 2, e这样就得到计算关键路径的算法。n为了简化算法, 假定在求关键路径之前已经对各顶点实现了拓扑排序, 并按拓扑有序的顺序对各顶点重新进行了编号。v5v1v2v3v4v6v7v8v9465112974426405771614181814108661670事件最早开始时间事件最早开始时间Ve事件事件最晚开始时间最晚开始时间Vlv5v1v2v3v4v6v7v8v9465112974426405771614181814108661670活动活动1-21-31-42-53-54-65-75-86-87-98-9e0006457771614l0236687710 1614l-e02302300300v5v1v2v7v8v9619742607161418181461670得到的关键路径得到的关键路径n并不是加快任何一个关键活动都可以缩短整个工程的工期。只有加快那些包括在所有关键路径上的关键活动才能达到这个目的。n关键活动的速度提高是有限度的。n提高到一定程度,不再是关键活动了作业P244n1n2n3n4n13n14(1)n15
展开阅读全文