定义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],int pre[maxn])
  4 //n个点,dist[i]表示向外延伸的最短边长,map记录图信息,pre[]记录连接信息,
  5 //dist之和最最小权值
  6 {
  7     int i,j,k;
  8     int min;
  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]<min)
 25             {
 26                 min=dist[j];
 27                 k=j;
 28             }
 29         }
 30         if(k==0)return;//如果没有点可以扩展,即图G不连通,返回
 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 struct HeapElement
 50 {
 51     int key,value;
 52 };
 53 struct MinHeap
 54 {
 55     HeapElement H[maxn];
 56     int size;
 57     int position[maxn];
 58     void init(){H[size=0].value=-INF;}
 59     void ins(int key,int value)
 60     void decrease(int key,int value)
 61     void delmin()
 62 }H;
 63 //
 64 struct edge
 65 {
 66     int to,w,next;
 67 }edge[maxm];
 68 int N,M;
 69 long long dist[maxn];
 70 int head[maxn];
 71 void Prim()
 72 {
 73     int i,j,k;
 74     bool p[maxn]={0};
 75     H.init(true);
 76     for(i=1;i<=N;i++)
 77     {
 78         H.ins(i,INF);
 79         dist[i]=INF;
 80     }
 81     dist[1]=0;
 82     H.decrease(1,0);
 83     for(i=1;;)
 84     {
 85         p[i]=true;
 86         H.delmin();//删除堆顶元素
 87         for(k=head[i];k!=-1;k=edge[k].next)
 88         {
 89             if(!p[j]&&edge[k].w<dist[j=edge[k].to])
 90             {
 91                 dist[j]=edge[k].w;
 92                 H.decrease(j,dist[j]);
 93             }
 94         }
 95         if(H.size)i=H.H[1].key;
 96         //扩展Vb中的点,以便下次更新
 97         else break;
 98     }
 99 }
100 
101 /*用堆优化的Prim算法主要用于加速变较少的图的最小生成树的计算,特别是稀疏图。
102 总的时间复杂度是O((n+m)log n).当边较少时,这种算法相对直接实现的Prim算法来说
103 有很好的效果。*/
View Code

相关文章:

  • 2022-12-23
  • 2021-04-04
  • 2021-06-18
  • 2022-12-23
  • 2021-08-08
  • 2021-12-29
  • 2021-07-17
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-10-13
  • 2022-12-23
  • 2021-04-10
  • 2021-09-20
相关资源
相似解决方案