最小生成树(MST)算法 Prim

/*--------------------------------------
* 最小生成树(MST)算法 Prim 和 Kruskal
* 所谓最小生成树(MST)就是构造连通网的最小代价的生成树。
* 举个例子:假设要在n个城市之间建立通信联络网,则连通n个城市只需要n-1条线路。
* 这就需要考虑一个问题,如何在最节省经费的前提下建立这个通信网。即在n(n-1)/2条线路中选出n-1条线路且网络连通,代价最小。
* 这便是最小生成树的经典应用实例。
* -------------------------------------*/

#include <iostream>
using namespace std;

#define MAX_VERTEX_NUM 100
#define VexType int
#define EdgeType int
#define MAXNUM 65535

// 采用邻接矩阵的方法表示图

typedef struct MGraph {
 VexType vex[MAX_VERTEX_NUM];
 EdgeType edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
 int vexnum, edgenum;
}MGraph;

// 图的创建
void CreateGraph(MGraph &G, int n, int e) {
 G.vexnum = n;
 G.edgenum = e;
 cout << "请输入你的顶点:" << endl;
 VexType v;
 for (int i = 0; i < G.vexnum; i++) {
  cin >> v;
  G.vex[i] = v;
 }
 for (int i = 0; i < n; i++) {
  for (int j = 0; j < n; j++) {
   G.edge[i][j] = MAXNUM;
  }
 }

 cout << "请输入你的边的信息:(例如顶点1与2之间有边权值为6,输入1 2 6)" << endl;
 int a, b, c;
 for (int i = 0; i < e; i++) {
  cin >> a >> b >> c;
  G.edge[a][b] = G.edge[b][a] = c;
 }
}

// 深度优先搜索
int visited[MAX_VERTEX_NUM];
void DFS(MGraph &G, int i) {
 visited[i] = 1;
 cout << G.vex[i] << "    ";
 for (int ii = 0; ii < G.vexnum; ii++) {
  if (G.edge[i][ii]!= MAXNUM && visited[ii] == 0) {
   DFS(G, ii);
  }
 }
}

void DFS_Traverse(MGraph &G) {
 for (int i = 0; i < G.vexnum; i++) {
  visited[i] = 0;
 }
 for (int i = 0; i < G.vexnum; i++)
 {
  if (!visited[i]) {
   DFS(G, i);
  }
 }
}

// Prim:从图G的第start个顶点出发的最小生成树
void MinSpanTree_Prim(MGraph &G,int start) {
 int index = 0; // prim最小树顶点的索引
 VexType *primTree = new VexType[G.vexnum];// primTree的结果数组
 int *weight = new int[G.vexnum]; // 顶点间边的信息
 int min; // 最小权值
 int minflag = 0;

 primTree[index] = G.vex[start];
 index++; // 初始化 从顶点start开始

 for (int i = 0; i < G.vexnum; i++) {
  weight[i] = G.edge[start][i];
 }

 weight[start] = 0; // weight[i] = 0 表示顶点i已经加入到生成树中

 for (int i = 0; i < G.vexnum; i++) {
  if (i == start)
   continue;
  min = MAXNUM;
  for (int j = 0; j < G.vexnum; j++) {
   if (weight[j] != 0 && weight[j] < min) {
    min = weight[j];
    minflag = j;
   }
  }
  primTree[index] = G.vex[minflag];
  index++;
  
  weight[minflag] = 0;

  for (int j = 0; j < G.vexnum; j++) {
   // 当第j个节点没有被处理,并且需要更新时才更新
   if (weight[j] != 0 && G.edge[minflag][j] < weight[j]) {
    weight[j] = G.edge[minflag][j];
   }
  }
 }

 // 计算最小生成树的权值
 int sum = 0;
 for (int i = 0; i < index; i++) {
  cout << primTree[i] << endl;
 }
}

int main() {
 MGraph G;
 int n, e;
 cout << "输入顶点数和边数:" << endl;
 cin >> n >> e;
 CreateGraph(G, n, e);
 DFS_Traverse(G);
 cout << endl;
 MinSpanTree_Prim(G, 0);
 system("pause");
 return 0;
}

原文地址:https://www.cnblogs.com/codingtao/p/6433627.html