图的连通性及最小生成树

合集下载

最小生成树的算法

最小生成树的算法

最小生成树的算法王洁引言:求连通图的最小生成树是数据结构中讨论的一个重要问题.在现实生活中,经常遇到如何得到连通图的最小生成树,求最小生成树不仅是图论的基本问题之一 ,在实际工作中也有很重要的意义,,人们总想寻找最经济的方法将一个终端集合通过某种方式将其连接起来 ,比如将多个城市连为公路网络 ,要设计最短的公路路线;为了解决若干居民点供水问题 ,要设计最短的自来水管路线等.而避开这些问题的实际意义 ,抓住它们的数学本质 ,就表现为最小生成树的构造。

下面将介绍几种最小生成树的算法。

一,用“破圈法”求全部最小生成树的算法1 理论根据1.1 约化原则给定一无向连通图 G =(V ,E )( V 表示顶点,E 表示边),其中 V={ 1v , 2v ,3v …… n v },E= { 1e , 2e , 3e …… n e }对于 G 中的每条边 e ∈ E 都赋予权ω(i e )>0,求生成树 T = (V ,H ),H ⊆ E ,使生成树所有边权最小,此生成树称为最小生成树.(1) 基本回路将属于生成树 T 中的边称为树枝,树枝数为n -1,不属于生成树的边称为连枝.将任一连枝加到生成树上后都会形成一条回路.把这种回路称为基本回路,记为()cf e 。

基本回路是由 T 中的树枝和一条连枝构成的回路.(2) 基本割集设无向图 G 的割集 S (割集是把连通图分成两个分离部分的最少支路集合) ,若 S 中仅包含有T 中的一条树枝,则称此割集为基本割集,记为()S e 。

基本割集是集合中的元素只有一条是树枝,其他的为连枝.(3) 等长变换设T=(V,H),为一棵生成树,e ∈ H, 'e ∈ E, 'e ∉ H,当且仅当'e ∈()cf e ,也就是说e ∈()S e ,则'T =T ⊕{e, 'e }也是一棵生成树。

当()e ω='()e ω时,这棵生成树叫做等长变换。

图的常用算法——最小生成树

图的常用算法——最小生成树

TE= {(V1,V4)5,(V4,V2)3 ,(V4,V6)7,
(V6,V3)2 ,(V3,V5)6 } LW= {(V4,V7)15
9
第六次 U={ V1,V4,V2 ,V6,V3 ,V5,V7 } TE= {(V1,V4)5,(V4,V2)3 ,(V4,V6)7, (V6,V3)2 ,(V3,V5)6},(V4,V7)15 } LW= { }
3
5
7
20
所以最小生成树由GE数组中的1,2,3,5,7 边组成。 2012-1-10
2012-1-10
10
2012-1-10
11
(4)算法如下: Procedure Prim(GA,CT); begin for I:=1 to n-1 do { 给CT赋初值,对应第0次的LW值 } [ CT[I].from :=1 ; ct[I].end: =I+1 ; ct[I].w:=GA[1, i+1 ]; for k:=1 to n-1 do { 进行n-1次循环,求出最小生成树的第K条边 } ①[ min:=maxint ; m:=k ; for j:=k to n-1 do if ct[j].w < min then min:=ct[j].w ; m:=j; ] ② if m<> k then ct[k] 与ct[m] 的交换 { 将最短边调到第K单元 }
1. 从图“G”的选取一个顶点放到“G’” 中,因只有一个顶点,因此该图是连通 的; 2. 以后每加入一个顶点,都要加入以该点 为顶点与已连通的顶点之中的一个顶点 为端点的一条边,使其既连通而不产生 回路,进行n-1次后,就产生G’,在G’ 中有n个顶点,n-1条边且不产生回路。
二、图的最小生成树

图的基本概念图的存储表示图的遍历与连通性 最小生成树最短路径汇总

图的基本概念图的存储表示图的遍历与连通性 最小生成树最短路径汇总



为了实现逐层访问, 算法中使用了一个队列, 以记忆正在访问的这一层和下一层的顶点, 以便于向下一层访问。 为避免重复访问, 需要一个辅助数组 visited [ ],给被访问过的顶点加标记。
深度优先搜索DFS ( Depth First Search )

深度优先搜索的示例
1
A
2
B
3
E G 4 I
1
A
2
B
C 5 H
3
E
G 4 I
7 D
6 F
C 5
H
7 D
6 F
前进 深度优先搜索过程来自89回退 深度优先生成树
8
9

DFS 在访问图中某一起始顶点 v 后, 由 v 出 发, 访问它的任一邻接顶点 w1; 再从 w1 出发, 访问与 w1邻 接但还没有访问过的顶点 w2; 然后再从 w2 出发, 进行类似的访问, … 如此 进行下去, 直至到达所有的邻接顶点都被访 问过的顶点 u 为止。接着, 退回一步, 退到 前一次刚访问过的顶点, 看是否还有其它没 有被访问的邻接顶点。如果有, 则访问此顶 点, 之后再从此顶点出发, 进行与前述类似 的访问; 如果没有, 就再退回一步进行搜索。 重复上述过程, 直到连通图中所有顶点都被 访问过为止。
邻接表 (Adjacency List)

无向图的邻接表
A
data adj 0 A 1 B 2 C 3 D dest link
dest link
1 0 1 0
3 2
B D
C
同一个顶点发出的边链接在同一个边链表 中,每一个链结点代表一条边(边结点), 结 点中有另一顶点的下标 dest 和指针 link。

最小生成树的模型数学公式

最小生成树的模型数学公式

最小生成树的模型数学公式
最小生成树的模型数学公式是:
给定无向连通图G(V,E),其中V为图的顶点集合,E为图的边集合。

每条边e∈E都带有一个非负权重w(e)。

找到一个包含图中所有顶点的子图T(V,E'),使得E' ⊆ E,并且E'构成一颗树(即连通且无环),使得所有的边的权重之和最小。

拓展:
最小生成树的应用十分广泛,可以用于解决多种问题。

以下是最小生成树的一些常见拓展场景:
1.带有约束条件的最小生成树:
在某些情况下,除了最小化权重之和外,还需要满足一些特定的约束条件。

例如,可以要求最小生成树的边数限制在特定的范围内,或者要求选择特定类型的边。

这时可以在最小生成树的模型中引入额外的约束条件,从而得到满足要求的最小生成树。

2.多目标最小生成树:
有时候,最小生成树问题不仅需要最小化权重之和,还需要考虑其他目标。

例如,可以同时考虑最小化权重之和和最大化生成树中的最长边权重。

这样的问题可以转化为多目标优化问题,并通过权衡不同目标之间的关系来求解。

3.带有边权重动态变化的最小生成树:
在某些场景中,图的边权重可能会根据一些规则进行动态变化。

例如,网络中的通信链路可能会根据网络拓扑和负载情况进行变化。

这时可以通过动态更新最小生成树来快速适应环境变化,从而保持最小生成树的有效性。

总之,最小生成树的模型可以通过引入不同的约束条件和目标函数进行拓展,以适应不同的应用场景。

最小生成树的两种构造方法

最小生成树的两种构造方法

离散数学大作业 ---最小生成树姓名:陈强学号:辅导老师:李阳阳一、最小生成树的概念:给定一个连通图,要求构造具有最小代价的生成树时,也即使生成树各边的权值总和达到最小。

把生成树各边的权值总和定义为生成树的权,那么具有最小权值的生成树就构成了连通图的最小生成树,最小生成树可简记为MST 。

二、构造无向连通图的最小生成树的方法:1.Prim (普里姆)算法算法:假设G(V,E)是有n 个顶点的无向连通图,用T(U,TE)表示要构造的最小生成树,其中U 为顶点集合,TE 为边的集合。

(1)初始化:令V={Φ} ,TE={Φ}。

从V 中取一个顶点u0放入生成树的顶点集U 中,作为第一个顶点,此时T=({u0},{Φ});(2)从U V v V u -∈∈,的边(u,v )中找一条代价最小的边*)*,(v u ,将其放入TE 中,并将*v 放入U 中。

(3)重复步骤(2),直至U=V 为止。

此时TE 集合中必有n -1条边,T 即为所要构造的最小生成树。

特殊处理:如果两个顶点之间没有直接相连的边,权值置为一个max 的数 自身和自身的权值置为MAX 的值代码:function [T]=Prim(i,G_dist)%Prim.m 实现了普里姆的方法生成无向连通图G 的最小生成树%T是返回的最小生成树%i为输入的为最小生成树选定的第一个顶点%G_dist是待输入的数据,是图G边(u,v)的权值矩阵[m,n]=size(G_dist);%读入无向图的顶点数目为m=nv=i;%将选定的顶点放入中间变量v中T=zeros(3,m-1);%最小生成树有(m-1)条边。

第一行存放边的起点,第二行存放边的终点,第三行存放边的权值%%%初始化最小生成树的矩阵for j=1:m-1T(1,j)=v;%将第一个顶点放入最小生成树的矩阵中if j>=vT(2,j)=j+1;T(3,j)=G_dist(v,j+1);elseT(2,j)=j;T(3,j)=G_dist(v,j);endend%%%求第k条边for k=1:(n-1)min=10000;%初始化一个最小的权值%找出最短边,并将最短变的下标记录在mid中for j=k:(n-1)if T(3,j)<minmin=T(3,j);mid=j;endende=T(:,mid);T(:,mid)=T(:,k);T(:,k)=e;%将最短的边所在的一列和第k列交换 v=T(2,k);%v中存放新找到的最短边在V-U中的顶点for j=(k+1):(n-1)%修改所存储的最小边集d=G_dist(v,T(2,j));if d<T(3,j)T(3,j)=d;T(1,j)=v;endendendDG=sparse(T(1,:),T(2,:),T(3,:),m,m);%用稀疏矩阵view(biograph(DG,[],'ShowArrows','off','ShowWeights','on'));%画图调用函数G=[10000,10,3,10000,10000,10000;10,10000,5,8,6,10000;3,5,10000,10000, 2,10000;10000,8,10000,10000,7,11;10000,6,2,7,10000,17;10000,10000,100 00,11,17,10000;];%G表示图G的各边权值,自身到自身的权值和不直接相连的顶点的权值设为10000i=1;T1=[1,2,1,3,2,2,4,4,5;3,3,2,5,5,4,5,6,6;3,5,10,2,6,8,7,11,17;0,0,0,0, 0,0,0,0,0];%T1表示图G的边的信息,第一行是边的起始点,第二行是边的终点,第三行是边的权重,第四行表示对边的选择T=T1(1:3,:);DG=sparse(T1(1,:),T1(2,:),T1(3,:),m,m);%用稀疏矩阵view(biograph(DG,[],'ShowArrows','off','ShowWeights','on'));%画图Prim(i,G);结果:图G:Prim生成的最小生成树:2.Kruskal(克鲁斯卡尔)算法算法:假设G(V,E)是有n个顶点的无向连通图。

最小生成树(Kruskal和Prim算法)

最小生成树(Kruskal和Prim算法)

最⼩⽣成树(Kruskal和Prim算法)关于图的⼏个概念定义:关于图的⼏个概念定义:连通图:在⽆向图中,若任意两个顶点vi与vj都有路径相通,则称该⽆向图为连通图。

强连通图:在有向图中,若任意两个顶点vi与vj都有路径相通,则称该有向图为强连通图。

连通⽹:在连通图中,若图的边具有⼀定的意义,每⼀条边都对应着⼀个数,称为权;权代表着连接连个顶点的代价,称这种连通图叫做连通⽹。

⽣成树:⼀个连通图的⽣成树是指⼀个连通⼦图,它含有图中全部n个顶点,但只有⾜以构成⼀棵树的n-1条边。

⼀颗有n个顶点的⽣成树有且仅有n-1条边,如果⽣成树中再添加⼀条边,则必定成环。

最⼩⽣成树:在连通⽹的所有⽣成树中,所有边的代价和最⼩的⽣成树,称为最⼩⽣成树。

构造最⼩⽣成树的准则有3条:(1)必须只使⽤该⽹络中的边来构造最⼩⽣成树。

(2)必须使⽤且仅使⽤n-1条边来连接⽹络中的n个顶点。

(3)不能使⽤产⽣回路的边。

下⾯介绍两种求最⼩⽣成树算法1 Prim(普利姆算法)算法--加点法此算法可以称为“加点法”,每次迭代选择代价最⼩的边对应的点,加⼊到最⼩⽣成树中。

算法从某⼀个顶点s开始,逐渐长⼤覆盖整个连通⽹的所有顶点。

Prim算法从任意⼀个顶点开始,每次选择⼀个与当前顶点集最近的⼀个顶点,并将两顶点之间的边加⼊到树中。

Prim算法在找当前最近顶点时使⽤到了贪婪算法。

实现过程:5int logo[1010];///⽤0和1来表⽰是否被选择过6int map1[1010][1010];7int dis[1010];///记录任意⼀点到这⼀点的最近的距离8int n,m;9int prim()10 {11int i,j,now;12int sum=0;13for(i=1;i<=n;i++)///初始化14 {15 dis[i]=MAX;16 logo[i]=0;17 }18for(i=1;i<=n;i++)19 {20 dis[i]=map1[1][i];21 }22 dis[1]=0;23 logo[1]=1;24for(i=1;i<n;i++)///循环查找25 {26 now=MAX;27int min1=MAX;28for(j=1;j<=n;j++)29 {30if(logo[j]==0&&dis[j]<min1)31 {32 now=j;33 min1=dis[j];34 }35 }36if(now==MAX)///防⽌不成图37 {38break;39 }40 logo[now]=1;41 sum=sum+min1;42for(j=1;j<=n;j++)///填⼊新点后更新最⼩距离,到顶点集的距离43 {44if(logo[j]==0&&dis[j]>map1[now][j])45 {46 dis[j]=map1[now][j];47 }48 }49 }50if(i<n)51 {52 printf("?\n");53 }54else55 {56 printf("%d\n",sum);57 }58 }59int main()60 {61while(scanf("%d%d",&m,&n)!=EOF)///n是点数62 {63if(m==0)64 {65break;66 }67 memset(map1,0x3f3f3f3f,sizeof(map1));///map是邻接矩阵储存图的信息68for(int i=0;i<m;i++)69 {70int a,b,c;71 scanf("%d%d%d",&a,&b,&c);72if(c<map1[a][b])///防⽌出现重边73 {74 map1[a][b]=map1[b][a]=c;75 }76 }77 prim();78 }79return0;80 }邻接表实现:1 #include<stdio.h>2 #include<string.h>3 #include<vector>4 #include<algorithm>5#define INF 0x3f3f3f3f6using namespace std;7struct node8 {9int end;///终点10int power;///权值11 } t;12int n;///n为点数13 vector<node>q[500001];///邻接表储存图的信息14int dis[500001];///距离15int vis[500001];///标记数组16void prime()17 {18int i,len,j,pos,sum,start;19 memset(vis,0,sizeof(vis));20 sum=0;21 start=1;///任意取起点22for(i=0; i<=n; i++)23 {24 dis[i]=INF;25 }26 len=q[start].size();27for(i=0; i<len; i++)///从任意起点开始的dis数组更新28 {29if(q[start][i].power<dis[q[start][i].end])30 {31 dis[q[start][i].end]=q[start][i].power;32 }33 }34 vis[start]=1;35for(j=0; j<n-1; j++)36 {37int pos,min=INF;38for(i=1; i<=n; i++)39 {40if(vis[i]!=0&&dis[i]<min)41 {42 min=dis[i];43 pos=i;///找到未访问节点中权值最⼩的44 }45 }46if(pos==INF)///防⽌不成图47 {48break;49 }50 vis[pos]=1;51 sum=sum+min;52 len=q[pos].size();///再次更新dis数组53for(j=0; j<len; j++)54 {55if(vis[q[pos][j].end]==0&&dis[q[pos][j].end]>q[pos][j].power)56 {57 dis[q[pos][j].end] = q[pos][j].power;58 }59 }60 }61if(j<n)62 {63 printf("?\n");64 }65else66 {67 printf("%d\n",sum);68 }69 }70int main()71 {72int m,i;73int begin,end,power;74int a,b;75while(scanf("%d%d",&n,&m)!=EOF)76 {77for(i=0; i<=n; i++)78 {79 q[i].clear();///将victor数组清空80 }81for(i=0; i<m; i++)82 {83 scanf("%d%d%d",&begin,&end,&power);///输⼊84 t.end=end;85 t.power=power;86 q[begin].push_back(t);87 t.end=begin;///⽆向图88 t.power=power;89 q[end].push_back(t);90 }91 prime();92 }93return0;94 }这⾥再给出⼀个没有使⽤标记数组的代码:int prim(int s){int i,j,sum=0;int now;for(i=1;i<=n;i++){closest[i]=INT_MAX;}for(i=1;i<=n;i++){closest[i]=map[s][i];}closest[s]=0;for(i=1;i<n;i++)//这⾥的i代表的是边数,有n个点就会有n-1条边{int min=INT_MAX;for(j=1;j<=n;j++){if(closest[j]&&closest[j]<min){min=closest[j];now=j;//找到所需的最⼩边}}sum+=min;closest[now]=0;//将找到的边加⼊到最⼩⽣成树之中for(j=1;j<=n;j++)//找到新的点加⼊已选点集合之后,更新该点到未选点集合的距离{if(map[now][j]&&map[now][j]<closest[j]){closest[j]=map[now][j];}}}return sum;}2 Kruskal(克鲁斯卡尔)算法--加边法1.概览 Kruskal算法是⼀种⽤来寻找最⼩⽣成树的算法,在剩下的所有未选取的边中,找最⼩边,如果和已选取的边构成回路,则放弃,选取次⼩边。

最小生成树定理

最小生成树定理

摘要:最小生成树(Minimum Spanning Tree,MST)是图论中的一个基本概念,它在网络设计、数据结构、算法设计等领域有着广泛的应用。

本文将详细介绍最小生成树定理的定义、性质、算法以及在实际应用中的重要性。

一、引言在图论中,一个图由顶点和边组成。

如果这个图是一个连通图,那么它的任意两个顶点之间都存在一条路径。

最小生成树定理研究的是如何从一个连通无向图中选择一些边,使得这些边构成一个连通子图,并且所有边的权值之和最小。

二、定义1. 图:由顶点集合V和边集合E组成,记为G=(V,E),其中V表示顶点集,E表示边集。

2. 连通图:对于图G中的任意两个顶点u、v,若存在一条路径连接u和v,则称图G是连通的。

3. 无向图:对于图G中的任意两个顶点u、v,若边(u,v)和边(v,u)同时存在,则称边(u,v)为无向边。

4. 权值:对于图G中的任意一条边(u,v),可以赋予一个非负实数w(u,v)作为权值。

5. 最小生成树:对于图G的一个连通子图T,如果满足以下两个条件,则称T为G 的最小生成树:(1)T是连通的;(2)T中的边权值之和最小。

三、性质1. 存在性:对于任意一个连通无向图,都存在一个最小生成树。

2. 唯一性:对于任意一个连通无向图,其最小生成树是唯一的。

3. 极小性:对于任意一个连通无向图,它的最小生成树中的边权值之和最小。

4. 极大性:对于任意一个连通无向图,它的最小生成树中的边权值之和最大。

四、算法1. 克鲁斯卡尔算法(Kruskal's Algorithm)(1)将图G中的所有边按照权值从小到大排序;(2)初始化一个空的最小生成树T;(3)遍历排序后的边,对于每条边(u,v):①检查边(u,v)是否与T中的任意一条边形成环;②若不形成环,则将边(u,v)加入T;(4)当T中的边数等于顶点数减1时,算法结束。

2. 普里姆算法(Prim's Algorithm)(1)从图G中选择一个顶点作为起始顶点v0;(2)初始化一个空的最小生成树T,并将v0加入T;(3)对于图G中的其他顶点v,初始化一个距离数组dist,其中dist[v]表示顶点v到T的距离,初始时dist[v]=∞(v≠v0);(4)遍历T中的顶点,对于每个顶点v,更新其相邻顶点的距离;(5)从距离数组中选择距离最小的顶点u,将其加入T;(6)重复步骤(4)和(5),直到T中的边数等于顶点数减1。

详解图的应用(最小生成树、拓扑排序、关键路径、最短路径)

详解图的应用(最小生成树、拓扑排序、关键路径、最短路径)

详解图的应用(最小生成树、拓扑排序、关键路径、最短路径)1.最小生成树:无向连通图的所有生成树中有一棵边的权值总和最小的生成树1.1 问题背景:假设要在n个城市之间建立通信联络网,则连通n个城市只需要n—1条线路。

这时,自然会考虑这样一个问题,如何在最节省经费的前提下建立这个通信网。

在每两个城市之间都可以设置一条线路,相应地都要付出一定的经济代价。

n个城市之间,最多可能设置n(n-1)/2条线路,那么,如何在这些可能的线路中选择n-1条,以使总的耗费最少呢?1.2 分析问题(建立模型):可以用连通网来表示n个城市以及n个城市间可能设置的通信线路,其中网的顶点表示城市,边表示两城市之间的线路,赋于边的权值表示相应的代价。

对于n个顶点的连通网可以建立许多不同的生成树,每一棵生成树都可以是一个通信网。

即无向连通图的生成树不是唯一的。

连通图的一次遍历所经过的边的集合及图中所有顶点的集合就构成了该图的一棵生成树,对连通图的不同遍历,就可能得到不同的生成树。

图G5无向连通图的生成树为(a)、(b)和(c)图所示:G5G5的三棵生成树:可以证明,对于有n 个顶点的无向连通图,无论其生成树的形态如何,所有生成树中都有且仅有n-1 条边。

1.3最小生成树的定义:如果无向连通图是一个网,那么,它的所有生成树中必有一棵边的权值总和最小的生成树,我们称这棵生成树为最小生成树,简称为最小生成树。

最小生成树的性质:假设N=(V,{ E}) 是个连通网,U是顶点集合V的一个非空子集,若(u,v)是个一条具有最小权值(代价)的边,其中,则必存在一棵包含边(u,v)的最小生成树。

1.4 解决方案:两种常用的构造最小生成树的算法:普里姆(Prim)和克鲁斯卡尔(Kruskal)。

他们都利用了最小生成树的性质1.普里姆(Prim)算法:有线到点,适合边稠密。

时间复杂度O(N^2)假设G=(V,E)为连通图,其中V 为网图中所有顶点的集合,E 为网图中所有带权边的集合。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{0,1,4,5,2,3} 当所有顶点均属于一个集合时,此时图的最小生成树就生成了。
Kruskal算法最坏情况下时间复杂性为O(eloge),其中e为图中边的数目。
解答疑问:学生根据本节内容提出疑惑的知识点,进行解答或 讨论。
小结本节内容: 7.4.1 无向图的连通分量和生成树;7.4.3 最小生成树。
练习
0
3
0
3
0
3
4
DFS生成树
4
BFS生成树
4
5
1
2
5
1
2
5
1
2
对于非连通图,每个连通分量中的顶点集和遍历时走过的边一起构成 若干棵生成树,这些连通分量的生成树组成非连通图的生成森林。例如, 图7.15(c)所示为G3的深度优先生成森林,它由三棵深度优先生成树组成。
最小生成树
问题背景: 假设要在n个城市之间建立通信联络网,则连通n个城市只 需要n-1条线路。这时,自然会考虑这样一个问题,如何在最 节省经费的前提下建立这个通信网。n个城市之间,最多可能 设置n(n-1)/2条线路,那么,如何在这些可能的线路中选择n1条,以使总的耗费最少呢? 分析问题(建立模型): 可以用连通网来表示n个城市以及n个城市间可能设置的通 信线路,其中网的顶点表示城市,边表示两城市之间的线路, 赋于边的权值表示相应的代价。现在,我们要选择这样一棵生 成树,也就是使总的耗费最少。这个问题就是构造连通网的最 小代价生成树(MinimumCostSpanningTree)(简称为最小生成树) 的问题。一棵生成树的代价就是树上各边的代价之和。
03
3
7
4
4
1
8
25 6
1
250ຫໍສະໝຸດ 3451
2
03
3
4
1
25
1
2
Kruskal算法构造最小生成树的过程
0
3
4
1
5
1
2
03
3
4
1
12 5
2
5
0
3
4
1
25
1
2
03
3
7
4
1
12 5
2
5
Kruskal算法的关键之处是在选取某条边时应判断该边是否与已是生成树的边 形成回路。一种解决方法是将图的顶点划分为集合。开始时假定n个顶点分属于n个 集合,即每个集合中有一个顶点。
如上例顶点集合为: {0},{1},{2},{3},{4},{5}
当确定图中某条边为最小生成树的一条边时,就将该边的两个顶点所属的两个 集合合并为一个,表示原来属于两个集合的各个顶点已被这条新的边连通。如果选 取的某条边的两个顶点属于同一个集合时,该边应舍去。例如,上述例中,当选取 完(4,5)、(1,5)和(0,4)三条边后,顶点的集合成为:
0 05700
第四次,选取的顶点:2
Closevertex 0
Lowcost
0
51404 00700
第五次,选取的顶点:3
Closevertex 0
Lowcost
0
51404 00000
分析算法:
第一个for循环的执行次数为n-1,第二个for循环中又嵌套了两个for 循环,执行的次数为2(n-1)2。所以Prim算法的时间复杂性为O(n2)。
图的连通性及最小生成树
教学主题:图的连通性及最小生成树
教学内容:7.4.1 无向图的连通分量和生成树;7.4.3 最小生 成树。
教学目的:学会利用遍历获取无向图的连通分量;理解图的生 成树;理解最小生成树并且掌握两种最小生成树的构造算法
教学重点、难点:生成树;最小生成树的构造
教学课时:2
无向图的连通分量和生成树
起初,我们将顶点0作为最小生成树的顶点,所以,closevertex[i]的 值为0,i=1,2,…,n-1。而lowcost[i]为边(0,i)的权,i=1,2,…, n-1。由于n个顶点的生成树共有n-1条边,所以,选择边的过程共需要重复 n-1次。每次扫描数组lowcost,找出当前与生成树中顶点最近的顶点,令 其为w,得到最小生成树的一条边(closevertex[w],w)。然后,令 lowcost[w]=0(表示顶点w已加入最小生成树中)。由于顶点w的加入会引 起lowcost和closevertex的变化,因此,一旦有一个新顶点加入到最小生 成树中,就需要根据具体情况修改数组lowcost和closevertex。
void prim(int matrix[n][n],int n){
lowcost[0] = 0;
closevertex[0]=0;
for (i=1;i<n;i++) {
lowcost[i] = matrix[0][i];
closevertex[i] = 0; }
for (i=1;i<n;i++) { mincost = HUGE; /*HUGE表示一个大于图中最大权的一个数*/
if ((matrix[k][j]<lowcost[j]) && (lowcost[j]!=0)) {
lowcost[j] = matrix[k][j];
closevertex[j] = k; }
}
}
用prim算法构造最小生成树过程中变量的变化情况:
初始
0 1 2 34 5
Closevertex 0
ALMJBFC DE GKHI 这三个顶点集分别加上所有依附于这些 顶点的边,便构成了非连通图G3的三个连 通分量。如图7.3(b)所示。
设E(G)为连通子图G中所有边的集合,则从图中任一顶点出发遍历图 时,必定将E(G)分成两个集合T(G)和B(G),其中T(G)是遍历过程中历经的 边的集合。显然,T(G)和图G中所有顶点一起构成连通图G的极小连通子 图,按照7.1节的定义,它是连通图的一棵生成树,并且称由深度优先搜索 得到的为深度优先生成树;由广度优先搜索得到的为广度优先生成树(注 意:生成树不唯一)。例如,图7.15(a)和(b)所示分别为G4的深度和广度 优先生成树。
2.Kruskal算法
Kruskal算法是按边的顺序来构造最小生成树的。其思想 是按图中边的权值由小到大顺序逐个选取边,若选中的边与已 是最小生成树的边不构成回路,就把此边作为最小生成树的边。 如果选取的边与已是最小生成树的边构成回路,则将此边舍去。 由于图是连通的,只要选择n-1条边即得到最小生成树。
Lowcost
0
00000 4 ∞∞3 ∞
第一次,选取顶点:4
Closevertex 0
Lowcost
0
00404 4 ∞7 0 1
第二次,选取顶点:5
Closevertex 0 5 5 4 0 4
Lowcost
0 26700
第三次,选取的顶点:1
Closevertex 0 5 1 4 0 4
Lowcost
{0,1,4,5},{2},{3} 下一条边(0,1)的两个顶点属于同一个集合,故舍去。构成边(1,2)的两 个顶点属于不同的集合,应加到生成树中,顶点集合成为:
{0,1,4,5,2},{3} 下一条边(2,5)的顶点也属于同一个集合应舍去,边(3,4)的两个顶点属 于不同的集合,可加到生成树中,顶点集合成为:
图的生成树不是唯一的,从不同的顶点出发可以生成不同的生成树, 但n个顶点的生成树一定有n-1条边,如果图带权,那么怎样才能求出其 最小生成树?这就是我们日常生活经常要考虑的问题?


1.Prim算法
Prim算法构造最小生成树的方法:最初生成树为空,即 没有一个结点和一条边,首先选择一个顶点作为生成树的根, 然后每次从不在生成树中的边中选择一条权值尽可能小的边, 为了保证加入到生成树中的边不会造成回路,与该边邻接的两 个顶点必须一个已经在生成树中,一个则不在生成树中,若连 通图中有n个顶点,则按这种条件选择n-1边就可以得到这个图 的最小生成树了。
k = i;
for (j= 1;j<n;j++)
if ((lowcost[j] < mincost) && (lowcost[j]!=0)) {
mincost = lowcost[j];
输出k与closevertex[k]
k = j; }
lowcost[k] = 0; for (j = 1;j<n;j++) /*调整lowcost和closevertex数组的值*/
在对无向图进行遍历时, 对于连通图,仅需从图中任一 顶点出发,进行深度优先搜索或广度优先搜索,便可访问到图 中所有顶点。对非连通图,则需从多个顶点出发进行搜索,而 每一次从一个新的起始点出发进行搜索过程中得到的顶点访问 序列恰为其各个连通分量中的顶点集。
例如,图7.3中的G3是非连通图,按照图 7.14所示G3的邻接表进行深度优先搜索遍 历,三次调用DFS过程(分别从顶点A、D和 G出发)得到的顶点访问序列为:
课后训练:掌握两种最小生成树的构造方法,完成相关习题。
作业布置:题集7.7
反馈小结:图的连通性,再详细点讲解连通分量;最小生成树 的生成方法,有必要作个比较;同时要让学生知道不同的存储 结构,又是如何实现的,最起码要理解过程。
03
3
7
4
4
1
8
25 6
1
2
5
Φ
0
03 4
1
25 1
5
Prim算法构造最小生成树的过程
03 4
2
03 4
1
5
03
3
7
4
1
25
1
2
5
03 4
相关文档
最新文档