1.实验用例
如下图所示的赋权图表示某七个城市及预先算出它们之间的一些直接通信成路造价(单位:万元),试给出一个设计方案,使得各城市之间既能够通信又使总造价最小并计算其最小值.
2实验原理和方法
为了求解最小代价,使花费的总代价最小,这是数学中经典的求解最小耗费生成树的算法。其核心思想是寻找每一步的最优解继而求得全局最优解。
为了求得最小耗费生成树,我们运用数学中经典的Krusal算法,此算法的核心思想是:
1、 假设该图G是不连通的,对该图的边以非降序权重新排列。
2、 对于排序表中的每条边,如果现在把它放入T不会形成回路的话,则把它加入到生成树T中;否则丢弃。(找到两个最小的。可以遍历)
3、 输出最小生成树的结果,得到我们想要的答案。
注:此题简单的思路就是将图转换为邻接矩阵转进行处理,其实就是转换为二维数组进行处理。默认为无穷大,当有权值则记下 权值大小,主要我们是全部遍历。然后找到的话,我们将此结点的flag置为1,并将找到的最小权值置为无穷大,理论上说,也可以不用置为无穷大了,因为已经将flag置为1了。
3、代码如下:
1: // third.cpp : 定义控制台应用程序的入口点。
2: //
3: #include "stdafx.h"
4: #include <stdio.h>
5: #include<iostream>
6: using namespace std;
7: #define N 100
8: #define MaxNum 65535 //带权值的邻接矩阵默认为最大值
9: int tb[N][N];
10: void prim(int n, int m,int flag[]) //找到最小权值的那个结点
11: {
12: int min;
13: int first;
14: int last;
15: min = tb[0][0];
16: for(int i = 0; i < n; i++ )
17: for(int j = 0; j < n; j++ )//这是一个对称矩阵,整个遍历
18: {
19: if((flag[j]!=1) &&(min > tb[i][j]))
20: {
21: min = tb[i][j];
22: first = i;
23: last = j;
24: }
25: }
26: flag[first] = 1;
27: flag[last] = 1;
28: tb[first][last] = MaxNum; //找到后,将原来的那个权值置为最大值
29: cout << "输出找到的结点:"<<first+1 <<" "<<last+1<< endl;
30: }
31:
32: int main()
33: {
34: int n, m;
35: int i, j;
36: int u, v, w; //u v可以理解为行列。
37: int flag[N] = {0,};
38: cout << "请输入所求图的顶点数目和边的数目:"<<endl;
39: cin >> n >> m;
40: //构造带权值的邻接矩阵
41: for(i = 0; i < n; i++)
42: for(j = 0; j < n; j++)
43: tb[i][j] = MaxNum;
44: cout <<"请输入两条边的节点序号以及他们的权值:"<< endl;
45: for(i = 0; i < m; i++)
46: {
47: cin >> u >> v >> w;//顶点从1开始
48: tb[u-1][v-1] = tb[v-1][u-1] = w; //矩阵存储的时候按0存储。
49: }
50: for(i = 0; i < n; i++)
51: {
52: for(j = 0; j < n; j++)
53: cout << tb[i][j] <<" ";
54: cout << endl;
55: }
56: for (int i = 0; i < n; i++ )
57: {
58: flag [i] = 0;
59: }
61: for(int j = 0; j < n ; j++) //遍历一次找到一个,这里的flag是整个的局部变量。其实是遍历了n次(n为顶点)二维数组。
62: {
63: prim(n,m,flag); // 形参:顶点1,以及所有的顶点数目n
64: }
65: return 0;
66: }
67:
4.实验结果
因而最后求得的最小耗费是:此时的最小耗费是:23+1+4+9+3+17=57(万元)