最小生成树之prim算法与kruskal算法

来源:互联网 发布:淘宝信用贷款 编辑:程序博客网 时间:2024/06/15 18:19

给定一个带权值的无向图,那么权值之和最小的生成树,我们就称之为最小生成树(MST)。

(1)Prim算法是图论中的一种算法,可在加权连通图里搜索最小生成树。由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(Vertex (graph theory)),且其所有边的权值之和亦为最小。

算法代码及其注释如下(首先请参考代码下面的链接理解算法流程):

#include<iostream>  #include<fstream>  using  namespace std;  #define MAX 100                 //暂时设图中一共有100个点#define MAXCOST 0x7fffffff     //long int 里的最大值int graph[MAX][MAX];         //图的邻接矩阵int prim(int graph[][MAX], int n)   //最小生成树函数 {      int lowcost[MAX];        //lowcost[i]的值为i点的权值    int mst[MAX];            //mst[i]的值为与i点(终点)相连的那条边的另一个点(始点)    int i, j, min, minid, sum = 0;  //min为当前次数预计连入最小生成树的最小权值(最小边的长度),minid为当前次数预计连入最小生成树的点,sum为当前次数最小生成树上权值之和    for (i = 2; i <= n; i++)      {          lowcost[i] = graph[1][i];    //表示i点到1点(当前最小生成树)的权值(边的长度)        mst[i] = 1;   //当前次数下与i点连接的边的另一个点都是1点    }      mst[1] = 0;  //表示11点已经在最小生成树内    for (i = 2; i <= n; i++)      {          min = MAXCOST;          minid = 0;      //每一次循环前恢复初始设定        for (j = 2; j <= n; j++)          {              if (lowcost[j] < min && lowcost[j] != 0) //寻找与当前最小生成树相连的最小权值(最短的边长)与相连的点(j点),同时确保j点不在当前最小生成树内             {                  min = lowcost[j];                  minid = j;       //赋值            }          }          cout << "V" << mst[minid] << "-V" << minid << "=" << min << endl;   //打印当前次数下由mst[minid]点接minid点,它们之间的边长(此时已确定为最短)min        sum += min;          lowcost[minid] = 0;  //将此时的mind点放入最小生成树内        for (j = 2; j <= n; j++)          {              if (graph[minid][j] < lowcost[j])              {                  lowcost[j] = graph[minid][j];  //重新确定j点与当前最小生成树间的最小权值(最短的边长)                mst[j] = minid;  //与j点相连的边的另一个点为minid点            }          }      }      return sum;  }  int main()  {      int i, j, k, m, n;      int x, y, cost;      ifstream in("input.txt");      in >> m >> n;//m=顶点的个数,n=边的个数      //初始化图G      for (i = 1; i <= m; i++)      {          for (j = 1; j <= m; j++)          {              graph[i][j] = MAXCOST;            graph[j][i] = MAXCOST;     //假设图中的每两个顶点间的距离为无穷大        }      }      //构建图G      for (k = 1; k <= n; k++)      {          in >> i >> j >> cost;   //输入两个点及这两点间的距离(权值)        graph[i][j] = cost;          graph[j][i] = cost;      }      //调用最小生成树函数      cost = prim(graph, m);      //输出最小权值和      cout << "最小权值和=" << cost << endl;      system("pause");      return 0;  }  

参考链接:
http://blog.csdn.net/yeruby/article/details/38615045

kruskal算法:
先构造一个只含 n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直到森林中只有一棵树,也即子图中含有 n-1 条边为止。

参考链接:
http://blog.csdn.net/luomingjun12315/article/details/47700237
(注释较少看着吃力)(优推)

http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html
(从邻接矩阵的角度来看两种算法)

原创粉丝点击