定义1 对于无向图G和一棵树T来说,如果T是G的子图,则称T为G的树,如果T是G的生成子图,则称T是G的生成树。
定义2 对于一个边上具有权值的图来说,其边权值和最小的生成树称做图G的最小生成树。
定理1 对于一个图G,如果图中的边权值都不相同,则图的最小生成树唯一。
最小生成树
求无向图的最小生成树主要有Prim算法和Kruskal算法。
1.Prim算法
(1)基本算法
将图G中的所有点V分成两个顶点集合Va和Vb。在计算过程中Va中的点为已经选好连接入生成树的点,否则属于Vb。最开始的时候Va包含任意选取的图G中的一个点u,其余的点属于Vb,算法结束时所有与u连通的点属于Va,其余的点仍留在Vb中。如果算法结束时Vb不为空,说明图G的生成树不存在,只存在生成森林。
代码如下:
1 //直接实现,邻接矩阵存储图
2 const int maxn=101;3 void Prim(int n,int dist[maxn],int map[maxn][maxn],intpre[maxn])4 //n个点,dist[i]表示向外延伸的最短边长,map记录图信息,pre[]记录连接信息,5 //dist之和最最小权值
6 {7 inti,j,k;8 intmin;9 bool p[maxn];//记录该点是否属于Va
10 for(i=2;i<=n;i++)11 {12 p[i]=false;13 dist[i]=map[1][i];14 pre[i]=1;15 }16 dist[1]=0;17 p[1]=true;18 for(i=1;i<=n-1;i++)//循环n-1次,每次加入一个点
19 {20 min=INT_MAX;21 k=0;22 for(j=1;j<=n;j++)23 {24 if(!p[j]&&dist[j]
31 p[k]=true;32 for(j=1;j<=n;j++)33 {34 if(!p[j]&&map[k][j]!=INT_MAX&&dist[j]>map[k][j])35 {36 dist[j]=map[k][j];37 pre[j]=k;38 }39 }40 }41 }42 //时间复杂度O(n^2);43
44 //堆实现
45 /*使用堆来保存Vb中每一点到Va中所有点的最短边长并维护其最小值,46 并在访问每条边的时候更新。先将所有的点插入堆,并将值赋为inf,47 将根赋值为0,通过松弛技术进行更新。*/
48 //堆
49 structHeapElement50 {51 intkey,value;52 };53 structMinHeap54 {55 HeapElement H[maxn];56 intsize;57 intposition[maxn];58 void init(){H[size=0].value=-INF;}59 void ins(int key,intvalue)60 void decrease(int key,intvalue