1、158第 8 章 图一、复 习要点图是一种重要的非线性结构。它的特点是每一个顶点都可以与其它顶点相关联,与树不同,图中各个顶点的地位都是平等的,对顶点的编号都是人为的。通常,定义图由两个集合构成:一个是顶点的非空有穷集合,一个是顶点与顶点之间关系(边) 的有穷集合。对图的处理要区分有向图与无向图。它的存储表示可以使用邻接矩阵,可以使用邻接表,前者属顺序表示,后者属链接表示。在本章着重讨论了图的深度优先搜索和广度优先搜索算法,附带引入了生成树与生成森林的概念。对于带权图,给出了最小生成树的两种方法:Prim 算法和 Kruskal 算法,后者使用了最小堆和并查集作为它的辅助求解手段。在解决最短路
2、径问题时,采用了逐步求解的策略。最后讨论了作工程计划时常用的活动网络。涉及的主要概念是拓扑排序和关键路径,在解决应用问题时它们十分有用。本章复习的要点是:1、基本知识点主要要求理解图的基本概念,包括图的定义、图的连通性、图的路径和路径长度、图中各顶点的度及度的度量、无向连通图的最大边数和最小边数,有向强连通图的最大边数与最小边数等。掌握图的存储表示,包括邻接矩阵和邻接表,以及这些存储表示上的典型操作,如构造、求根、找第一个邻接顶点、找下一个邻接顶点等操作的实现算法。并要求掌握图的两种遍历算法:深度优先搜索和广度优先搜索算法,以及求解连通性问题的方法。理解求解关节点及构造重连通图的方法。此外,要
3、求掌握构造最小生成树的 Prim 算法和Kruskal 方法,掌握活动网络的拓扑排序算法,掌握求解关键路径的方法。需要注意的是,让某个关键活动提前完成,是否能让整个工程提前完成。2、算法设计 建立无向带权图的邻接表的算法,要求输入边的数目随机而定。 图的深度优先搜索的递归算法。 利用图的深度优先搜索的递归算法建立图的深度优先生成森林( 用左子女右兄弟表示)的算法。 图的广度优先搜索算法。 利用图的广度优先搜索算法建立图的广度优先生成森林(用左子女右兄弟表示) 的算法。 求解最小生成树的 Prim 算法,注意 nearvex 和 lowcost 辅助数组的变化。 求解最小生成树的 Kruskal
4、 算法,注意 minheap 和 UFset 的变化。 求解最短路径的 dijkstra 算法,注意 dist 辅助数组的变化。 有向图中求解拓扑排序的算法,要求用邻接表作为图的存储表示。注意算法执行过程中入度为零的顶点栈的变化。 有向图中求解拓扑排序的算法,要求用邻接矩阵作为图的存储表示。二、 难点和重点1、图:图的定义与图的存储表示 邻接矩阵表示(通常是稀疏矩阵 ) 邻接表与逆邻接表表示,要求建立算法 邻接多重表(十字链表 )表示1592、深度优先遍历与广度优先遍历 生成树与生成树林的定义 深度优先搜索算法和广度优先搜索算法 深度优先搜索是个递归的过程,而广度优先搜索是个非递归的过程 为防
5、止重复访问已经访问过的顶点,需要设置一个访问标志数组 visited3、图的连通性 深度优先搜索可以遍历一个连通分量上的所有顶点 对非连通图进行遍历,可以建立一个生成森林 对非强连通图进行遍历,可能建立一个生成森林 关节点的求解方法和以最少的边构成重连通图的方法4、最小生成树 对于连通网络、可用不会构成环路的权值最小的 n-1 条边构成最小生成树 会画出用 Kruskal 算法及 Prim 算法构造最小生成树的过程5、单源最短路径 采用逐步求解的方式求某一顶点到其他顶点的最短路径的方法 要求每条边的权值必须大于零6、活动网络 拓扑排序、关键路径、关键活动、AOE 网 拓扑排序将一个偏序图转化为
6、一个全序图。 为实现拓扑排序,要建立一个栈,将所有入度为零的顶点进栈 关键路径的计算三、教材中习题的解析8-1 画出 1 个顶点、2 个顶点、3 个顶点、4 个顶点和 5 个顶点的无向完全图。试证明在 n个顶点的无向完全图中,边的条数为 n(n-1)/2。【解答】【证明】在有 n 个顶点的无向完全图中,每一个顶点都有一条边与其它某一顶点相连,所以每一个顶点有 n-1 条边与其他 n-1 个顶点相连,总计 n 个顶点有 n(n-1)条边。但在无向图中,顶点 i 到顶点 j 与顶点 j 到顶点 i 是同一条边,所以总共有 n(n-1)/2 条边。8-2 右边的有向图是强连通的吗?请列出所有的简单路
7、径。【解答】判断一个有向图是否强连通,要看从任一顶点出发是否能够回到该顶点。右面的有向图做不到这一点,它不是强连通的有向图。各个顶点自成强连通分量。所谓简单路径是指该路径上没有重复的顶点。从顶点 A 出发,到其他的各个顶点的简单路径有AB , ADB,AB C ,AD BC,AD,AB E,AD E,ADBE,AB C FE,ADB CFE,A B CF,ADBCF。1 个顶点的无向完全图2 个顶点的无向完全图 3 个顶点的无向完全图4 个顶点的无向完全图 5 个顶点的无向完全图ABCDEF160010010Edge从顶点 B 出发,到其他各个顶点的简单路径有BC ,B C F ,B E ,B
8、 C F E。从顶点 C 出发,到其他各个顶点的简单路径有 CF,CFE。从顶点 D 出发,到其他各个顶点的简单路径有DB , DB C,DBC F,D E,D B E,D BCFE。从顶点 E 出发,到其他各个顶点的简单路径无。从顶点 F 出发,到其他各个顶点的简单路径有 FE。8-3 给出右图的邻接矩阵、邻接表和邻接多重表表示。【解答】 (1) 邻接矩阵(2) 邻接表(3) 邻接多重表(十字链表)0 A1 B2 C3 D4 E5 F0 3101 3 52(出边表)(入边表)data fin fout i j ilink jlinkABCDEF32 451 44 10 A1 B2 C3 D4
9、 E5 F0 A1 B2 C3 D4 E5 F0 3 (A, D)3 1 (D, B)0 1 (A, B)1 2 (B, C)1 4 (B, E)5 4 (F, E)3 4 (D, E)2 5 (C, F)161或8-4 用邻接矩阵表示图时,若图中有 1000 个顶点,1000 条边,则形成的邻接矩阵有多少矩阵元素?有多少非零元素?是否稀疏矩阵?【解答】一个图中有 1000 个顶点,其邻接矩阵中的矩阵元素有 10002 = 1000000 个。它有 1000个非零元素(对于有向图)或 2000 个非零元素(对于无向图) ,因此是稀疏矩阵。8-5 用邻接矩阵表示图时,矩阵元素的个数与顶点个数是否
10、相关?与边的条数是否相关?【解答】用邻接矩阵表示图,矩阵元素的个数是顶点个数的平方,与边的条数无关。矩阵中非零元素的个数与边的条数有关。8-6 有 n 个顶点的无向连通图至少有多少条边?有 n 个顶点的有向强连通图至少有多少条边?试举例说明。【解答】n 个顶点的无向连通图至少有 n-1 条边,n 个顶点的有向强连通图至少有 n 条边。例如:特例情况是当 n = 1 时,此时至少有 0 条边。8-7 对于有 n 个顶点的无向图,采用邻接矩阵表示,如何判断以下问题: 图中有多少条边?任意两个顶点 i 和 j 之间是否有边相连?任意一个顶点的度是多少?【解答】用邻接矩阵表示无向图时,因为是对称矩阵,
11、对矩阵的上三角部分或下三角部分检测一遍,统计其中的非零元素个数,就是图中的边数。如果邻接矩阵中 Aij 不为零,说明顶点 i 与顶点 j 之间有边相连。此外统计矩阵第 i 行或第 i 列的非零元素个数,就可得到顶点 i 的度数。8-8 对于如右图所示的有向图,试写出:(1) 从顶点出发进行深度优先搜索所得到的深度优先生成树;(2) 从顶点出发进行广度优先搜索所得到的广度优先生成树; 【解答】(1) 以顶点为根的深度优先生成树(不唯一): (2) 以顶点为根的广度优先生成树: 1628-9 试扩充深度优先搜索算法,在遍历图的过程中建立生成森林的左子女-右兄弟链表。算法的首部为 void Grap
12、h:DFS ( const int v, int visited , TreeNode * t ) 其中,指针 t指向生成森林上具有图顶点 v 信息的根结点。 (提示:在继续按深度方向从根 v 的某一未访问过的邻接顶点 w 向下遍历之前,建立子女结点。但需要判断是作为根的第一个子女还是作为其子女的右兄弟链入生成树。 )【解答】为建立生成森林,需要先给出建立生成树的算法,然后再在遍历图的过程中,通过一次次地调用这个算法,以建立生成森林。te mplate void Graph : DFS_Tree ( const int v, int visited , TreeNode *t ) /从图的顶点
13、 v 出发, 深度优先遍历图, 建立以 t (已在上层算法中建立)为根的生成树。Visitedv = 1; int first = 1; TreeNode * p, * q;int w = GetFirstNeighbor ( v ); /取第一个邻接顶点while ( w != -1 ) /若邻接顶点存在if ( vositedw = 0 ) /且该邻接结点未访问过p = new TreeNode ( GetValue (w) ); /建立新的生成树结点if ( first = 1 ) /若根*t 还未链入任一子女 t-setFirstChild ( p ); first = 0; /新结点
14、*p 成为根*t 的第一个子女else q-setNextSibling ( p ); /否则新结点*p 成为*q 的下一个兄弟q = p; /指针 q 总指示兄弟链最后一个结点DFS_Tree ( w, visited, q ); /从*q 向下建立子树w = GetNextNeighbor ( v, w ); /取顶点 v 排在邻接顶点 w 的下一个邻接顶点下一个算法用于建立以左子女-右兄弟链表为存储表示的生成森林。template void Graph : DFS_Forest ( Tree int n = NumberOfVertices ( ); /顶点个数TreeNode * p,
15、 * q;int * visited = new int n ; /建立访问标记数组for ( int v = 0; v ( GetValue ( v ) ); /建立新结点*pif ( T.root = NULL ) T.root = p; /原来是空的生成森林, 新结点成为根else q- setNextSibling ( p ); /否则新结点*p 成为*q 的下一个兄弟q = p;DFS_Tree ( v, visited, p ); /建立以*p 为根的生成树 8-10 用邻接表表示图时,顶点个数设为 n,边的条数设为 e,在邻接表上执行有关图的遍历操作时,时间代价是 O(n*e)?
16、还是 O(n+e)?或者是 O(max(n,e)?163【解答】在邻接表上执行图的遍历操作时,需要对邻接表中所有的边链表中的结点访问一次,还需要对所有的顶点访问一次,所以时间代价是 O(n+e)。8-11 右图是一个连通图,请画出 (1) 以顶点为根的深度优先生成树;(2) 如果有关节点,请找出所有的关节点。(3) 如果想把该连通图变成重连通图,至少在图中加几条边?如何加?【解答】(1) 以顶点为根的深度优先生成树: (2) 关节点为 ,(3) 至少加四条边 (1, 10), (3, 4), (4, 5), (5, 6)。从的子孙结点到的祖先结点引一条边,从的子孙结点到根的另一分支引一条边,并
17、将的子孙结点、与结点连结起来,可使其变为重连通图。8-12 试证明在一个有 n 个顶点的完全图中,生成树的数目至少有 2n-1-1。【证明】略511 76810978-13 编写一个完整的程序,首先定义堆和并查集的结构类型和相关操作,再定义Kruskal 求连通网络的最小生成树算法的实现。并以右图为例,写出求解过程中堆、并查集和最小生成树的变化。 164【解答】求解过程的第一步是对所有的边,按其权值大小建堆:1 3 113 4 51 2 7 2 3 102 4 9 1 3 111 2 72 4 9 2 3 101 2 71 3 11 2 3 10加(1, 2), (1, 3), (2,3)加(
18、2, 4) 加(3, 4)1651 3 113 4 51 2 7 3 5 72 4 9 2 3 10 3 6 81 2 73 4 55 6 6 3 5 72 4 9 2 3 10 3 6 81 3 11求解过程中并查集与堆的变化: 1 3 115 6 61 2 7 3 5 72 4 9 2 3 10 3 6 81 3 112 3 10 1 3 11 2 3 102 4 91 3 113 4 51 2 7 3 5 72 4 9 2 3 10加(3, 5) 加(3, 6)加(5, 6)选(3,4,5)选(5,6,6) 1 3 111 2 73 5 72 4 9 2 3 103 6 8选(1,2,7
19、)1 3 113 5 72 4 92 3 103 6 8选(3,5,7) 1 3 112 4 9 2 3 103 6 8 166最后得到的生成树如下3 1 -6 3 3 5 0 1 2 3 4 5 6完整的程序如下:#include template class MinHeap public:enum MaxHeapSize = 50 ;MinHeap ( int Maxsize = MaxHeapSize );MinHeap ( Type Array , int n );void Insert ( const Type void RemoveMin ( Type void Output ()
20、;private:void FilterDown ( int start, int end );void FilterUp ( int end );Type *pHeap;int HMaxSize;int CurrentSize;class UFSets public:enum MaxUnionSize = 50 ;UFSets ( int MaxSize = MaxUnionSize );UFSets () delete m_pParent; void Union ( int Root1, int Root2 );int Find ( int x );private:int m_iSize;
21、int *m_pParent;class Graph public:enum MaxVerticesNum = 50 ;Graph( int Vertices = 0) CurrentVertices = Vertices; InitGraph(); 67579选(3,6,8), 在同一连通分量上, 不加 选(2,4,9), 结束并查集的存储表示167void InitGraph ();void Kruskal ();int GetVerticesNum () return CurrentVertices; private:int EdgeMaxVerticesNumMaxVerticesNu
22、m;int CurrentVertices;class GraphEdge public:int head, tail;int cost;int operator cost = 0 ) x = m_pParentx;return x;template MinHeap : MinHeap ( int Maxsize ) HMaxSize = Maxsize; pHeap = new TypeHMaxSize;CurrentSize = -1;template MinHeap : MinHeap ( Type Array, int n ) HMaxSize = ( n = 0 ) FilterDo
23、wn ( iPos, CurrentSize );iPos-;template void MinHeap : FilterDown ( int start, int end ) int i = start, j = 2 * start + 1;Type Temp = pHeapi;while ( j void MinHeap : FilterUp ( int end ) int i = end, j = ( end - 1 ) / 2;Type Temp = pHeapi;while ( i 0 ) if ( pHeapj void MinHeap : Insert ( const Type
24、if ( CurrentSize = HMaxSize ) return;pHeapCurrentSize = ele;FilterUp ( CurrentSize );template void MinHeap : RemoveMin ( Type i heap ( VerticesNum *VerticesNum );UFSets set ( VerticesNum );for ( i = 0; i 0 ) e.head = i; e.tail = j; e.cost = Edgeij;heap.Insert ( e );count = 1;while ( count = 0 ) p =
25、disJointp;while ( disJointq = 0 ) p = disJointq;if ( p != q ) disJointj = i; / i 与 j 不在同一连通分量上, 连通之 else / i 与 j 在同一连通分量上p = i; /寻找离结点 i 与 j 最近的祖先结点while ( disJointp = 0 ) /每变动一个 p, 就对 q 到根的路径检测一遍q = j;while ( disJointq = 0 if ( disJointq = disJointp ) break;else p = disJointp;k = disJointp; /结点 k 是
26、 i 和 j 的最近的共同祖先p = i; q = disJointp; max = -MaxNum; /从 i 到 k 找权值最大的边(s1, s2)while ( q max ) max = Edgeqp; s1 = p; s2 = q; p =q; q = disJointp;p = j; q = disJointp; max = -MaxNum; /从 j 到 k 找权值最大的边(t1, t2)while ( q max ) max = Edgeqp; t1 = p; t2 = q; p =q; q = disJointp;max = Edgeij; k1 = i; k2 = j;if
27、 ( max = 0 /未选定最短路径顶点链表int i, k, u; ListNode * p;T. MakeEmpty ();for ( i = 1; i vertex.len = p-length; p = p-link; while (1) T.First (); /循环检测链表 Tif ( ! T.NextNotNull( ) ) break; /链表仅剩一个顶点, 跳出循环, 算法结束float min = MaxNum; u = 0;while ( T.NotNull( ) ) /链表不空, 还有剩余顶点未确定最短路径i = T.GetData( ); /取剩余顶点号if ( S
28、i.len vertex; /顶点 k 在链表 T 中表示该顶点未最终选定最短路径if ( T.Find(k) != NULL Sk.pre = u; /修改p = p-link;T.Find(u); T.Remove(); /在链表 T 中删除顶点 u 1748-17 试证明:对于一个无向图 G = (V, E),若 G 中各顶点的度均大于或等于 2,则 G 中必有回路。【解答】反证法:对于一个无向图 G=(V,E) ,若 G 中各顶点的度均大于或等于 2,则 G 中没有回路。此时从某一个顶点出发,应能按拓扑有序的顺序遍历图中所有顶点。但当遍历到该顶点的另一邻接顶点时,又可能回到该顶点,没有
29、回路的假设不成立。8-18 设有一个有向图存储在邻接表中。试设计一个算法,按深度优先搜索策略对其进行拓扑排序。并以右图为例检验你的算法的正确性。【解答】(1) 利用题 8-16 定义的邻接表结构。增加两个辅助数组和一个工作变量: 记录各顶点入度 int indegreeNumVertices。 记录各顶点访问顺序 int visitedNumVertices,初始时让 visitedi = 0, i = 1, 2, , NumVertices。 访问计数 int count,初始时为 0。(2) 拓扑排序算法void Graph : dfs ( int visited , int indegr
30、ee , int v, int visitedv = count;cout vertex;indegreew-;if ( visitedw = 0 p = p-link;主程序int i, j; Edge *p; float w;cin NumVertices;int * visited = new intNumVertices+1;int * indegree = new intNumVertices+1;for ( i = 1; i NodeTablei.data; cout i j w; cout link = NodeTablei.adj; NodeTablei.adj = p;Num
31、Edges+; 175cin i j w; cout e 0 0 15 19 19 15 29 38l 17 0 15 27 19 27 37 38l-e 17 0 0 8 0 12 8 0此工程最早完成时间为 43。关键路径为8-20 若 AOE 网络的每一项活动都是关键活动。令 G 是将该网络的边去掉方向和权后得到的无向图。 (1) 如果图中有一条边处于从开始顶点到完成顶点的每一条路径上,则仅加速该边表示的活动就能减少整个工程的工期。这样的边称为桥(bridge) 。证明若从连通图中删去桥,将把图分割成两个连通分量。(2) 编写一个时间复杂度为 O(n+e)的使用邻接表表示的算法,判断连通
32、图 G 中是否有桥,若有。输出这样的桥。【解答】(1) 反证法(略)(2) 借助于求重连通分量的算法。如果一条边的两个端点满足下列条件之一,即为桥:176 两个端点都是关节点; 一个端点是关节点,另一端点是整个图的开始点; 一个端点是关节点,另一端点是整个图的完成点。四、其他 练习题8-21 判断题(1) 用邻接矩阵存储一个图时,在不考虑压缩存储的情况下,所占用的存储空间大小只与图中的顶点个数有关,而与图的边数无关。(2) 邻接表只能用于有向图的存储,邻接矩阵对于有向图和无向图的存储都适用。(3) 邻接矩阵只适用于稠密图(边数接近于顶点数的平方) ,邻接表适用于稀疏图(边数远小于顶点数的平方)
33、 。(4) 有 n (n1) 个顶点的无向连通图最少有 n-1 条边。(5) 有 n (n1) 个顶点的有向强连通图最少有 n 条边。(6) 存储无向图的邻接矩阵是对称的,因此只要存储邻接矩阵的下(上)三角部分就可以了。(7) 连通分量是无向图中的极小连通子图。(8) 强连通分量是有向图中的极大强连通子图。(9) 对任何用顶点表示活动的网络(AOV 网)进行拓扑排序的结果都是唯一的。(10) 有回路的有向图不能完成拓扑排序。(11) 在 AOE 网络中一定只有一条关键路径。(12) 关键活动不按期完成就会影响整个工程的完成时间。(13) 任何一个关键活动提前完成, 那么整个工程将会提前完成。(
34、14) 所有的关键活动都提前完成, 那么整个工程将会提前完成。(15) 任何一个关键活动延迟,那么整个工程将会延迟。【解答】(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) 8-22 填空题 (1) 在一个无向图中,所有顶点的度数之和等于所有边数的_倍。(2) 在一个具有 n 个顶点的无向完全图中,包含有_条边,在一个具有 n 个顶点的有向完全图中,包含有_条边。 (3) 在一个具有 n 个顶点的无向图中,要连通所有顶点则至少需要 _条边。(4) 表示图的三种存储结构为_、_和_ 。(5) 对于一个具有 n 个顶
35、点的图,若采用邻接矩阵表示,则矩阵大小为 _。(6) 对于一个具有 n 个顶点和 e 条边的有向图和无向图,在其对应的邻接表中,所含边结点分别为_和_条。(7) 在有向图的邻接表和逆邻接表表示中,每个顶点的边链表中分别链接着该顶点的所有_和_结点。(8) 对于一个具有 n 个顶点和 e 条边的有向图和无向图,若采用邻接多重表表示,则存于顶点表中的边链表指针分别有_和_个,所有边结点有_个。(9) 对于一个具有 n 个顶点和 e 条边的无向图,当分别采用邻接矩阵、邻接表和邻接多重表表示时,求任一顶点度数的时间复杂度依次为_、_和_。177(10) 假定一个图具有 n 个顶点和 e 条边,则采用邻
36、接矩阵、邻接表和邻接多重表表示时,其相应的空间复杂度分别为_、_和_。(11) 对用邻接矩阵表示的图进行任一种遍历时,其时间复杂度为_,对用邻接表表示的图进行任一种遍历时,其时间复杂度为_。(12) 对于一个具有 n 个顶点和 e 条边的连通图,其生成树中的顶点数和边数分别为_和_。【解答】(1) 2 (2) n(n-1)/2, n(n-1)(3) n-1 (4) 邻接矩阵, 邻接表 , 邻接多重表(5) n2 (6) e, 2e(7) 出边, 入边 (8) 2n, n, e(9) O(n), O(e/n), O(e) (10) O(n2), O(n+e), O(n+e)(11) O(n2),
37、 O(e) (12) n, n-18-23 从供选择的答案中选择与下面有关图的叙述中各括号相匹配的词句,将其编号填入相应的括号内。 (1) 采用邻接表存储的图的深度优先遍历算法类似于二叉树的( A ) 。 (2) 采用邻接表存储的图的广度优先遍历算法类似于二叉树的( B ) 。(3) 对于含有 n 个顶点和 e 条边的无向连通图,利用 prim 算法产生最小生成树,其时间复杂性为( C ) ,利用 Kruskal 算法产生最小生成树,其时间复杂性为( D ) 。(4) 设图中有 n 个顶点和 e 条边,进行深度优先搜索的时间复杂度至多为( E ) ,进行广度优先搜索的时间复杂性至多为( F )
38、 。(5) 对于一个具有 n 个顶点和 e 条边的无向图,进行拓扑排序时,总的时间为( G ) 。(4) 判断有向图是否存在回路,除了可以利用拓扑排序方法外,还可以利用( H ) 。供选择的答案A, B: 中序遍历 前序遍历 后序遍历 按层次遍历C, D: O(n 2) O(n*e) O(nlog 2n) O(elog 2e)E, F: O(n+e) O(n*e) O(nlog 2n) O(elog 2e)G: n n+1 n-1 n+eH: 求关键路径的方法 求最短路径的 Dijkstra 方法 深度优先遍历算法 广度优先遍历算法【解答】A B C D E F G H8-24 若设一个图采用
39、邻接矩阵表示,试编写进行深度优先搜索的非递归算法。【解答】邻接矩阵采用教材中的定义。在相应的深度优先搜索的非递归算法中,同样使用了一个辅助数组 int visited ,在 visitedi中记忆第 i 个顶点是否访问过。另外,算法中使用了一个栈 S,记忆回退的路径。具体算法实现如下:#include #include “stack.h”template void Graph : : dfss ( int v ) /从顶点 v 开始进行深度优先搜索,一次遍历一个连通分量的所有顶点int i, j, k; Stack S; S.Push ( v );178int vositedMaxNumVer
40、tices;for ( i = 0; i = 0; j- ) /检查 k 的所有邻接顶点if ( k != j 8-25 应用 Prim 算法求解连通网络的最小生成树问题。(1) 针对右图所示的连通网络,试按如下格式给出在构造最小生成树过程中顺序选出的各条边。( 始顶点号,终顶点号, 权值 )( , , )( , , )( , , )( , , )( , , )(2) 下面是 Prim 算法的实现,中间有 5 个地方缺失,请阅读程序后将它们补上。const int MaxInt = INT_MAX; /INT_MAX 的值在中 const int n = 6; /图的顶点数, 应由用户定义ty
41、pedef int AdjMatrixnn; /用二维数组作为邻接矩阵表示typedef struct /生成树的边结点int fromVex, toVex; /边的起点与终点int weight; /边上的权值 TreeEdgeNode;typedef TreeEdgeNode MSTn-1; /最小生成树定义void PrimMST ( AdjMatrix G, MST T, int rt ) /从顶点 rt 出发构造图 G 的最小生成树 T,rt 成为树的根结点TreeEdgeNode e; int i, k = 0, min, minpos, v;for ( i = 0; i 中 co
42、nst int n = 6; /图的顶点数, 应由用户定义typedef int AdjMatrixnn; /用二维数组作为邻接矩阵表示int distance ( AdjMatrix A, intfor ( k = 0; k s ) s = Aij; /求顶点 i 到其他顶点最短路径中的长者180if ( s min ) k = i; min = s; /在各最长路径中选最短者return k;8-27 画出下图所示的 AOV 网的所有拓扑有序序列。【解答】共有 8 种: A D B E C F A D B E F C A D E B C F A D E B F CD A B E C F D A B E F C D A E B C F D A E B F CA B CD E F