1 / 77

第七章 图

第七章 图. 第七章 图 7.1 图的定义和术语 7.2 图的存储结构 7. 3 图的遍历 7.4 图的连通性问题 7.5 有向无环图及应用 7.6 最短路径. 第七 章 图. 本章介绍另一种非线性数据结构 —— 图 图:是一种多对多的结构关系,每个元素可以有零个或多个直接前趋;零个或多个直接后继;. 第七 章 图. 学习要点 1.熟悉图的各种存储结构及其构造算法,了解实际问题的求解效率与采用何种存储结构和算法有密切联系;

Télécharger la présentation

第七章 图

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第七章 图

  2. 第七章 图 7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的连通性问题 7.5 有向无环图及应用 7.6 最短路径

  3. 第七 章 图 本章介绍另一种非线性数据结构 —— 图 图:是一种多对多的结构关系,每个元素可以有零个或多个直接前趋;零个或多个直接后继;

  4. 第七 章 图 学习要点 1.熟悉图的各种存储结构及其构造算法,了解实际问题的求解效率与采用何种存储结构和算法有密切联系; 2.熟练掌握图的两种遍历:深度优先遍历和广度优先遍历的算法。在学习中应注意图的遍历算法与树的遍历算法之间的类似和差异。树的先根遍历是一种深度优先搜索策略,树的层次遍历是一种广度优先搜索策略 3.理解课件中讨论的各种图的算法;

  5. 7.1 图的定义和术语 V4 V2 V3 V1 V5 一 图的概念 图G由两个集合构成,记作G=<V,E> 其中V是顶点的非空有限集合,E是边的有限集合,其中边是顶点的无序对或有序对集合。 例 G1=<V1,E1> V1={v1,v2,v3,v4 ,v5 } E1={(v1,v2),(v1,v3),(v2,v3),(v2,v5),(v3,v4),(v3,v5)} 无序对(vi,vj): 用表示顶点vi、vj的线段 ,称为无向边; G1图示

  6. 7.1 图的定义和术语 V1 V2 V3 V4 例 G2=<V2,E2> V2={v1,v2,v3,v4 } E2={<v1,v2>, <v1,v3>, <v3,v4> , <v4,v1>} V1称为弧尾(初始点) 有序对<vi,vj> : 用以表示以vi起点、以vj 为终点的有向线段, 称为有向边或弧; G2图示 V3称为弧头(终端点) 无向图:在图G中,若所有边是无向边,则称G为无向图; 有向图:在图G中,若所有边是有向边,则称G为有向图; 混和图:在图G中,即有无向边也有有向边,则称G为混合图;

  7. 7.1 图的定义和术语 V4 V2 V3 V1 V5 • 图的应用举例 • 例1 交通图(公路、铁路) • 顶点:地点 • 边:连接地点的公路 • 交通图中的有单行道双行道,分别用有向边、无向边表示; • 例2 电路图 • 顶点:元件 • 边:连接元件之间的线路 • 例3 通讯线路图 • 顶点:地点 • 边:地点间的连线 • 例4 各种流程图 • 如产品的生产流程图 • 顶点:工序 • 边:各道工序之间的顺序关系

  8. 7.1 图的定义和术语 三 图的基本操作 1 CreateGraph(&G, V, VR); 初始条件:V是图的顶点集,VR是图中弧的集合 操作结果:按V和VR的定义构造图G 2 DestroyGraph(&G); 初始条件:图G存在 操作结果:销毁图G 3 LocateVex(G,u); 初始条件:图G存在,u和G中顶点有相同特征 操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回其它信息。 4 GetVex(G, v); 初始条件:图G存在,v是G中某个顶点 操作结果:返回v的值 5 PutVex(&G, v, value); 初始条件:图G存在,v是G中某个顶点 操作结果:对v赋值value

  9. 7.1 图的定义和术语 6 FirstAdjVex(G, v); 初始条件:图G存在,v是G中某个顶点 操作结果:返回v的第一个邻接顶点。若顶点在G中没有邻接顶点,则返回“空”。 7 NextAdjVex(G, v, w); 初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点。 操作结果:返回v的(相对于w的)下一个邻接顶点。若w是v的最后一个邻接点,则返回“空”。 8 InsertVex(&G, v); 初始条件:图G存在,v和图中顶点有相同特征。 操作结果:在图G中增添新顶点v 9 DeleteVex(&G, v); 初始条件:图G存在,v和图中顶点有相同特征 操作结果:删除G中顶点v及相关的弧

  10. 7.1 图的定义和术语 10 InsertArc(&G, v, w); 初始条件:图G存在,v和w是G中两个顶点。 操作结果:在G中增添弧<v,w>,若G是无向的,则还增添对称弧<w,v> 11 DeleteArc(&G, v, w); 初始条件:图G存在,v和w是G中两个顶点。 操作结果:在G中删除弧<v,w>,若G是无向的,则还删除对称弧<w,v> 12 DFSTraverse(G, v, Visit( )); 初始条件:图G存在,v是G中某个顶点,Visit是顶点的应用函数。 操作结果:从顶点v起深度优先遍历图G,对每个顶点调用函数Visit一次且仅一次。一旦visit( )失败,则操作失败 13 BFSTraverse(G, v, Visit( )); 初始条件:图G存在,v是G中某个顶点,Visit是顶点的应用函数。 操作结果:从顶点v起广度优先遍历图G,对每个顶点调用函数Visit一次且一次。一旦visit( )失败,则操作失败

  11. 7.1 图的定义和术语 V4 V2 V1 V3 V2 V3 V4 V1 V5 • 图的基本术语 • 1 邻接点及关联边 • 邻接点:边的两个顶点 • 关联边:若边e= (v, u), 则称顶点v、u 关联边e • (边e 依附于顶点v,u) • 2 顶点的度、入度、出度顶点V的度=与V相关联的边的数目 • 在有向图中: • 顶点V的出度=以V为起点有向边数 • 顶点V的入度=以V为终点有向边数 • 顶点V的度= V的出度+V的入度 • 设图G的顶点数为n,边数为e • 图的所有顶点的度数和 = 2*e • (每条边对图的所有顶点的度数和“贡献”2度) e1

  12. 3 有向完全图、无向完全图 有向完全图——n个顶点的有向图最大边数是n(n-1) 无向完全图——n个顶点的无向图最大边数是n(n-1)/2 权(weight)——与图的边或弧相关的数叫~ 网——带权的图叫~ 7.1 图的定义和术语

  13. 7.1 图的定义和术语 V4 V2 V3 V1 V2 V3 V4 V1 V5 • 路径、回路 • 无向图中的顶点序列v1,v2,… ,vk,若(vi,vi+1)E( i=1,2,…k-1), v =v1, u =vk,则称该序列是从顶点v到顶点u的路径;若v=u,则称该序列为回路; • 有向图D=(V,E)中的顶点序列v1,v2,… ,vk, 若<vi,vi+1>E ( i=1,2,…k-1), v =v1, u =vk, 则称该序列是从顶点v到顶点u的路径;若v=u,则称该序列为回路; • 例 • 在图1中,V1,V2,V3,V4 是V1到V4的路径; V1,V2,V3,V4,V1是回路;在图2中,V1,V3,V4 是V1到V4的路径; V1,V3,V4,V1是回路; 图1 图2

  14. 7.1 图的定义和术语 V4 V2 V2 V5 V6 V1 V3 V4 V1 V5 V3 • 连通图、(强连通图) • 在无(有)向图G=< V, E >中,若对任何两个顶点v、u都存在从v • 到u的路径,则称G是连通图(强连通图) 连通图 非连通图

  15. 7.1 图的定义和术语 V4 V4 V2 V2 V2 V3 V3 V3 V1 V1 V1 V5 V5 V5 • 子图 • 设有两个图G=(V,E)、G1=(V1,E1),若V1 V,E1  E,E1关联的顶点都在V1中,则称 G1是G的子图; • 例 图2、图3 是 图1 的子图 图2 图1 图3

  16. 7.1 图的定义和术语 V2 V5 V6 V1 V4 V3 • 连通分图(强连通分量) • 无向图G的极大连通子图称为G的连通分量 • 极大连通子图意思是:该子图是G连通子图,将G的任何不在该子图中的顶点加入,子图不再连通; • 有向图D的极大强连通子图称为D的强连通分量 • 极大强连通子图意思是:该子图是D强连通子图,将D的任何不在该子图中的顶点加入,子图不再是强连通的; 连通分图

  17. 7.1 图的定义和术语 V4 V4 V2 V2 V3 V3 V1 V1 V5 V5 8 生成树( 包含无向图G所有顶点的的极小连通子图称为G生成树 极小连通子图意思是:该子图是G的连通子图,在该子图中删除任何一条边,子图不再连通, 若T是G的生成树当且仅当T满足如下条件 T是G的连通子图 T包含G的所有顶点 T中无回路 只有足以构成一棵树的n-1条边

  18. 例 例 2 2 4 4 5 5 无向完全图 有向完全图 1 1 3 3 6 6 G1 2 2 1 3 1 3 例 1 5 7 图与子图 3 2 4 6 G2 5 顶点5的度:3 顶点2的度:4 顶点2入度:1 出度:3 顶点4入度:1 出度:0 3 6

  19. 2 4 5 1 3 6 G1 例 1 5 7 3 2 4 6 G2 路径:1,2,3,5,6,3 路径长度:5 简单路径:1,2,3,5 回路:1,2,3,5,6,3,1 简单回路:3,5,6,3 路径:1,2,5,7,6,5,2,3 路径长度:7 简单路径:1,2,5,7,6 回路:1,2,5,7,6,5,2,1 简单回路:1,2,3,1

  20. 2 4 5 1 3 6 例 例 2 4 5 5 1 3 6 3 6 连通图 强连通图 非连通图连通分量

  21. 第七 章 图 • 7.2 图的存储结构 • 数组表示法 • 邻接表

  22. 7.2 图的存储结构 图是多对多的结构,比线性结构、树结构复杂,所以其存储结构也要复杂些。与线性结构、树结构一样,图的存储结构至少要保存两类信息: 1)顶点的数据 2) 顶点间的关系 顶点的编号 为了使图的存储结构与图一一对应,在讨论图的存储结构时,首先要给图的所有顶点编号。 本课程介绍两类图的存储结构 数组表示法 邻接表(邻接表,逆邻接表) 设 G=<V, E>是图, V={v1,v2,v3, …vn },设顶点的的角标为它的编号 如何表示顶点间的关系? ?

  23. 7.2 图的存储结构 V4 V2 V3 V1 V2 V3 V4 • 0 1 0 1 0 • 0 1 0 1 • 0 1 0 1 1 • 0 1 0 0 • 0 1 1 0 0 • 0 1 1 0 • 0 0 0 0 • 0 0 0 1 • 0 0 0 V1 V5 一 数组表示法 数组表示法是图的一种顺序存储结构 在数组表示法中,用邻接矩阵表示顶点间的关系 邻接矩阵:G的邻接矩阵是满足如下条件的n阶矩阵: 1 若(vi,vi+1)E 或 <vi,vi+1>E 0 否则 A[i][j]=

  24. 7.2 图的存储结构 0 1 0 1 0 1 0 1 0 1 0 1 2 3 4 m m+1m+2 m+3m+4 V1 V2 V3 V4 V5 0 1 2 3 4 5 m-1 数组表示法 顶点的存储:用一维数组存储(按编号顺序) 顶点间关系:用二维数组存储图的邻接矩阵; 存储顶点的 一维数组 存储邻接矩阵的 二维数组

  25. 7.2 图的存储结构 数组表示法类型定义 #define INFINITY INT_MAX #define MAX_VERTEX_NUM 20 typedef enum{DG, DN, AG, AN} GraphKind; typedef struct ArcCell { VRType adj; InfoType *info; }ArcCell, AdjMatrix[MAX_VERTEX_NUM ][MAX_VERTEX_NUM ] typedef struct { VetexType vexs[MAX_VERTEX_NUM ]; AdjMatrix arc; int vexnum, arcnum; GraphKind kind; }MGraph;

  26. 7.2 图的存储结构 顶点数组 V1 0 n e AG G.vexs G.arcs G.vexnumG.arcnu G.kind 存储邻接矩阵的二维数组 设G是Mgraph 类型的变量,用于存储无向图,该图有n个顶点,e条边 G的图示如下:

  27. 7.2 图的存储结构 无向图数组表示法特点: 1)无向图邻接矩阵是对称矩阵,同一条边表示了两次; 2)顶点v的度:等于二维数组对应行(或列)中1的个数; 3)判断两顶点v、u是否为邻接点:只需判二维数组对应分量是否为1; 4)顶点不变,在图中增加、删除边:只需对二维数组对应分量赋值1或清0; 5)设存储顶点的一维数组大小为m(m图的顶点数n), G占用存储空间:m+m2;G占用存储空间只与它的顶点数有关,与边数无关;适用于边稠密的图; 对有向图的数组表示法可做类似的讨论

  28. 7.2 图的存储结构 该结点表示边 (V1 V2),其中的1是V2在一维数组中的位置 0 1 2 3 4 m-1 V1 V2 V3 V4 V5 4 0 V4 V2 V3 1 3 0 4 1 3 2 V1 1 2 V5 • 邻接表 • 邻接表是图的链式存储结构 • 1 无向图的邻接表 • 顶点:通常按编号顺序将顶点数据存储在一维数组中; • 关联同一顶点的边:用线性链表存储 例

  29. 7.2 图的存储结构 图的邻接表类型定义 #define MAX_VERTEX_NUM 20 typedef struct ArcNode{ //边(弧)结点的类型定义 int adjvex; //边(弧)的另一顶点的在数组中的位置 struct ArcNode *nextarc; //指向下一条边(弧)结点的指针 InfoType *info; }ArcNode; typedef struct VNode { //顶点结点和数组的类型定义 VertexType data; //顶点信息 ArcNode * finrstarc; //指向关联该顶点的边(弧)链表 }VNode, AjList[MAX_VERTEX_NUM]; typedef struct { AdjList vertices; int vexnum, arcnum; //图的当前顶点数和弧数 int kind; //图的种类标志 }ALGraph;

  30. 7.2 图的存储结构 0 1 2 4 m-1 data firstarc adjvex nextarc 4 0 V4 V2 V3 G.vertices G.vexnum G.arcnu G.kind V1 V2 V3 V4 V5 1 3 0 4 1 3 2 V1 1 2 V5 n e AG 设G是ALGraph 类型的变量,用于存储无向图G1,该图有n个顶点,e条边 G的图示如下: 该结点表示边 (V5,V2),其中的1是V2在一维数组中的位置 无向图G1

  31. 7.2 图的存储结构 无向图的邻接表的特点 1)在G邻接表中,同一条边对应两个结点; 2)顶点v的度:等于v对应线性链表的长度; 3)判定两顶点v ,u是否邻接:要看v对应线性链表中有无对应的结点 4)在G中增减边:要在两个单链表插入、删除结点;

  32. 7.2 图的存储结构 V1 V2 V3 V4 0 1 3 2 有向图的邻接表和逆邻接表 1)有向图的邻接表 顶点:用一维数组存储(按编号顺序) 以同一顶点为起点的弧:用线性链表存储 D.vertices D.vexnum D.arcnu D.kind V1 V2 V3 V4 2 例 类似于无向图的邻接表, 所不同的是: 以同一顶点为起点的弧: 用线性链表存储 n e DG

  33. 7.2 图的存储结构 D.vertices D.vexnum D.arcnu D.kind V1 V2 V3 V4 V1 V2 V3 V4 3 0 0 2 n e DG 2)有向图的逆邻接表 顶点:用一维数组存储(按编号顺序) 以同一顶点为终点的弧:用线性链表存储表 类似于无向图的邻接表, 所不同的是: 以同一顶点为终点的弧: 用线性链表存储

  34. 7.2 图的存储结构 在不同的存储结构下,实现各种操作的效率可能是不同的。所以在求解实际问题时,要根据求解问题所需操作,选择合适的存储结构。

  35. 第七 章 图 7.3 图的遍历 一 深度优先遍历 二 广度优先遍历

  36. 7.3 图的遍历 图的遍历:从图的某顶点出发,访问图中所有顶点,并且每个顶点仅访问一次。 图中可能有回路,遍历可能沿回路又回到已遍历过的结点。为避免同一顶点被多次访问,必须为每个被访问的顶点作一标志。为此引入一辅助数组, 记录每个顶点是否被访问过。 有两种遍历方法(它们对无向图,有向图都适用): 深度优先遍历 广度优先遍历

  37. 7.3 图的遍历 V3 V5 V8 V2 V1 V6 V4 V7 一 深度优先遍历 从图中某顶点v出发: 1)访问顶点v;2)从v的未被访问的邻接点出发,继续对图进行深度优先遍历; 注:为简单起见, 只讨论非空连通图的遍历 这是序列(1)在遍历过程中所经过的路径 例图G中,以V1起点的的深度优先序列: (1) V1,V2,V4,V5,V8,V3,V6,V7, (2) V1,V2,V5,V8,V4,V3,V6,V7 由于没为有规定 访问邻接点的顺序, 深度优先序列不是唯一的

  38. 7.3 图的遍历 V3 V5 V8 V2 V1 V6 V4 V7 深度优先遍历(设图为非空连通图) 从图中某顶点v出发: 1)访问顶点v;2)从v的未被访问的邻接点出发, 继续对图进行深度优先遍历; 先序遍历(DLR) 若二叉树非空 (1)访问根结点; (2)先序遍历左子树; (3)先序遍历右子树; 如果将图顶点的邻接点 看作二叉树结点的左、右孩子 深度优先遍历与先序遍历 是不是很类似?

  39. 7.3 图的遍历 0 0 0 0 0 visited 0 1 2 3 4 m-1 Boolean visited[MAX_VERTEX_NUM] //访问标志数组,全局变量,初始值:所有分量全为False(0) //visited[v]=TRUE表示顶点v已被访问 深度优先遍历算法 void DFS(Graph G, int v, Status(*Visit(int v)) { // 从第v个顶点出发,递归地深度优先遍历图G。 // v是顶点在一维数组中的位置,假设G是非空图 visited[v] =TRUE; Visit(v); //访问第v个顶点 for (w= FirstAdjVex(G, v); w; w=NextAdjVex(G, v, w)) if (!visited[w]) DFS(G, w); //对v的尚未访问的邻接顶点w递归调用DFS

  40. 7.3 图的遍历 深度优先遍历算法 void DFS(Graph G, int v, Status(*Visit(int v)) { // 从第v个顶点出发,递归地深度优先遍历图G。 // v是顶点在一维数组中的位置,假设G是非空图 visited[v] =TRUE; Visit(v); //访问第v个顶点 for (w= FirstAdjVex(G, v); w; w=NextAdjVex(G, v, w)) if (!visited[w]) DFS(G, w); //对v的尚未访问的邻接顶点w递归调用DFS 先序遍历递归算法void PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e)) {//本算法先序遍历以T为根结点指针的二叉树。 if (T) { //若二叉树为空,结束返回 Visit(T->data); PreOrderTraverse(T->lchild, Visit); PreOrderTraverse(T->rchild, Visit); }//PreOrderTraverse 如果将图顶点的邻接点 看作二叉树结点的左、右孩子 深度优先遍历算法与 先序遍历算法 的结构是不是很像?

  41. 7.3 图的遍历 V3 V5 V8 V2 V1 V6 V4 V7 • 广度优先遍历(类似于树的按层遍历) • 从图中某顶点v出发: • 1)访问顶点v ; • 2)访问v的所有未被访问的邻接点w1 ,w2 ,…wk ; • 3)依次从这些邻接点出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问; • 例图G中,以V1起点的的广度优先序列: • (1)V1,V2,V3,V4,V5,V6,V7,V8 • (2)V1,V3,V2,V6,V7,V4,V5,V8 这是序列(1)在遍历过程中所经过的路径 由于没为有规定 访问邻接点的顺序, 广度优先序列不是唯一的

  42. 7.3 图的遍历 广义优先遍历算法 从图中某顶点v出发: 1)访问顶点v ;(容易实现) 2)访问v的所有未被访问的邻接点w1 ,w2 ,…wk ; (容易实现) 3)依次从这些邻接点(在步骤 2)访问的顶点)出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问; 为实现 3),需要保存在步骤(2)中访问的顶点,而且访问这些顶点邻接点的顺序为:先保存的顶点,其邻接点先被访问。 在广度优先遍历算法中,需设置一队列Q, 保存已访问的顶点,并控制遍历顶点的顺序。

  43. 7.3 图的遍历 void BFSTraverse(Graph G,int v,Status (* Visit)(int v)) { //从v出发,广度优先遍历连通图G。 v是顶点在一维数组中的位置,使用辅助队列Q和访问标志数组visited。 for (u=0; u< G.vexnum; ++u) visited[u]=FALSE; InitQueue(Q); //建空的辅助队列Q Visited[v]=TRUE; Visit(v),EnQueue(Q,v) //访问v,v入队 While(!QueueEmpty(Q)){ DeQueue(Q,u); //队头元素出队,并赋值给u //访问u所有未被访问的邻接点 for(w=FirstAdjVex(G,u); w; w=NextAdjVex(G,u,w)) if(!visited[w]){ // 若w尚未访问 Visited[w]=TRUE; Visit(w);EnQueue(Q,w); }//if }//while }//BFSTraverse

  44. 7.3 图的遍历 V2 V2 V1 V5 V6 V1 V5 V6 V4 V4 V3 V3 非连通图的遍历 上面介绍了连通图的深度优先遍历算法,对非连通图,可从每个连通分量选一起点,调用遍历算法(如DFS)完成各连通分量的深度先遍历。 例 图G的深度优先序列:V1,V2,V3,V4,V5,V6, 广度优先序列 V1,V2,V3,V4,V5,V6, 深度优先遍历所经过的路径 广度优先遍历所经过的路径

  45. 7.4.1 图的连通性问题--无向图的连通分量和生成树 生成树 定义:所有顶点均由边连接在一起,但不存在回路的图叫~ 深度优先生成树与广度优先生成树 生成森林:非连通图每个连通分量的生成树一起组成非连通图的~ 7.4 图的连通性

  46. 7.4.1 图的连通性问题--无向图的连通分量和生成树 说明 一个图可以有许多棵不同的生成树 所有生成树具有以下共同特点: 生成树的顶点个数与图的顶点个数相同 生成树是图的极小连通子图 一个有n个顶点的连通图的生成树有n-1条边 生成树中任意两个顶点间的路径是唯一的 在生成树中再加一条边必然形成回路 含n个顶点n-1条边的图不一定是生成树 G K I H

  47. V1 V1 V2 V3 V2 V3 V4 V5 V6 V7 V4 V5 V6 V7 V1 V8 V1 V8 V2 V3 V2 V3 V4 V6 V4 V5 V6 V7 V1 例 V8 V7 V2 V3 V8 广度优先生成树 V5 V4 V5 V6 V7 深度优先生成树 V8 深度遍历:V1 V2 V4  V8 V5 V3 V6 V7 广度遍历:V1 V2 V3  V4 V5 V6 V7 V8

  48. A B C D E F G H D A I K L C F E J M L M B J G K I 深度优先生成森林 H

  49. void DFSTree(Graph G,int v ,CSTree *T) {/*从第v个顶点出发深度优先遍历图G,建立以*T为根的生成树*/ visited[v]=TRUE; first=TRUE; for(w=FirstAdjVex(G,v); w; w=NextAdjVex(G,v,w)) if(!visited[w]) { p=(CSTree)malloc(sizeof)CSNode)); /*分配孩子结点*/ *p={GetVex(G,w),NULL,NULL}; if (first) /*w是v的第一个未被访问的邻接顶点,作为根的左孩子结点*/ { T->lchild=p; first=FALSE; } else { /*w是v的其它未被访问的邻接顶点,作为上一邻接顶点的右兄弟*/ q->nextsibling=p; } q=p; DFSTree(G,w,&q); /*从第w个顶点出发深度优先遍历图G,建立生成子树*q*/ } }

  50. 7.4 图的连通性 • 7.4.3 最小生成树 • n个城市之间,最多可能设置n(n-1)/2条线路,而连通n个城市只需要n-1条线路. • 最小(代价)生成树的定义. • 一棵生成树的代价.

More Related