prim算法是利用最小生产树的MST性质来一点一点的构造最小生成树的。
假设N={V,{E}}是一个带权值的无向图(即为一个网),U是顶点集V的一个非空子集, 若(u,v)是一个具有最小权值的边,其中u属于U,v属于V-U,则必然存在一个包含(u,v)边的最小生成树。
关于MST的证明:点击打开链接
prim算法分析:(使用邻接矩阵来存储网)
1:要知道T1顶点集合连接到T2顶点集合中最小权值的边,就是从T1集合中选一个顶点t1,从T2集合分钟选一个顶点,使得(t1,t2)的权值最小,其中T2集合是已经构成最小生成树一部分的顶点。
2:要知道T1中哪个顶点和T2中哪个顶点构成的边具有最小权值。
解决一问题使用:lowcost[MAX]数组,用来记录可能权值最小的顶点和权值信息。比如lowcost[k] = 78,就表示T2顶点集合中的某个顶点和第k个顶点(来自于T1)组成的边权值是78,有可能是最小的权值。
解决二,使用lowcost[MAX],我们知道了T1集合的第k个顶点和T2中的某个顶点可能构成最小权值边,但是我们不知道T2中的某个点是哪个,所以我们可以使用vertex[MAX]来记录。
如果单纯的要计算最少的代价总和,而不要记录顶点的顺序,就不需要vertex数组了。
如果从顶点v1开始构建最小生成树进行如下步骤:
1:初始化lowcost和vertex数组
for (int i = 1;i <= n;i++)
{
lowcost[i] = Matrix[1][i];//v1与邻接点构成的边的权值。
vertex[i] = 1;
}
lowcost[1] = 0;//表示v1顶点加入了T2集合中,
2:遍历lowcost[MAX]数组,选择其中值最小的且值不为0的权值所在的下标k,然后lowcost[k] = 0;表示将第k个顶点加入T2集合中,我们可以打印出此时的边
printf ("%d %d %d",vertex[k],k,lowcost[k]);//这个时候vertex就有用了。
3:进行到这里我们知道第k个顶点加入集合T2中了,这个要改变lowcost和vertex,
for (i = 1;i <= n;i++) {
if (lowcost[i] != 0 && Matrix[k][i] < lowcost[i]) {
lowcost[i] = Matrix[k][i];
vertex[i] = k;
}
}
2,3步骤是一个在T1中取顶点的过程,不断的进行2,3步骤直至U=V为止,这个就完成的了最小生成的树的构造。
#include "stdio.h"
#include "string.h"
#define MAX 20
#define INF 100000000
int Matrix[MAX][MAX];
//n顶点的数量,v表示从第几个顶点开始构造最小生成树
int minimum_cost_spanning_tree (int n,int v) {
int least_weight_sum = 0;
int lowcost[MAX];
int vertex[MAX];
int i,j;
for (i = 1;i <= n;i++) {
lowcost[i] = Matrix[v][i];
vertex[i] = v;
}
lowcost[v] = 0;//表示将Vv加入U集合中
for (i = 1;i < n;i++) {//从V-U集合筛选出顶点放入U集合中
int min = INF;
for (j = 1;j <= n;j++) {
if (lowcost[j] != 0 && lowcost[j] < min) {
min = lowcost[j];
v = j;
}
}
printf ("%d %d %d\n",vertex[v],v,lowcost[v]);
least_weight_sum += lowcost[v];
lowcost[v] = 0;//表示将Vv加入U集合中
for (j = 1;j <= n;j++) {
if (Matrix[v][j] < lowcost[j]) {
lowcost[j] = Matrix[v][j];
vertex[j] = v;
}
}
}
return least_weight_sum;
}
void print (int n) {
int i;
int j;
for (i = 1;i <= n;i++) {
for (j = 1;j <= n;j++){
printf ("%10d ",Matrix[i][j]);
}
printf ("\n");
}
}
int main () {
int i,j;
int n,m;//n边数,m顶点数
int v,u,w;//v和u表示某条边依附的二个顶点 w为权值
memset (Matrix,0,sizeof(Matrix));
scanf ("%d%d",&n,&m);
for (i = 0;i <n;i++) {
scanf ("%d%d%d",&v,&u,&w);
Matrix[v][u] = Matrix[u][v] = w;
}
for (i = 1;i <= m;i++) {
for (j = 1;j <= m;j++) {
if (i != j && Matrix[i][j] == 0) {
Matrix[i][j] = INF;
}
}
}
print (m);
printf ("-------\n");
minimum_cost_spanning_tree (m,1);
return 0;
}