描述:
使用prim算法求某图的最小生成树的边的权值输出的序列。例如下图的最小生成树的权值输出序列为1 4 2 5 3,要求从V1顶点开始生成最小生成树。
输入:
若干行整数
第一行为两个整数,分别为图的顶点数和边数
第二行开始是该图的邻接矩阵,主对角线统一用0表示,无直接路径的两点用100来表示(保证各边权值小于100)
输出:
若干用空格隔开的整数
样例输入:
6 10
0 6 1 5 100 100
6 0 5 100 3 100
1 5 0 5 6 4
5 100 5 0 100 2
100 3 6 100 0 6
100 100 4 2 6 0
样例输出:
1 4 2 5 3
prim算法——加点法
这么加点呢?举个例子就懂了:
代码中的变量意义:
int dain,bian; // 点,边;
int ljb[120][120]; // 图对应的邻接表;
// ljb[x][y] = z ,意味着点 x 到点 y 的权是 z;
int a[120],b[120];
// 最小边集合 重点!!!
// a[x] = y; b[x] = z;
// 表示目前 “最小树点集合” 到其他点的最近距离
// 为位置点 x 到 点 y 的权为 z;使用两个一维数组表示邻接表中的信息;
int juge[120];
// (juge[i] == 0) 判断点i已经加到最小树里面了;
代码区:
#include<iostream>
#include<cstring>
using namespace std;
int a[120],b[120];
int ljb[120][120];
int dian,bian;
int juge[120];
int main()
{
memset(juge,1,sizeof(juge)); // 初始化全为1,为0表示该点已加入最小生成树
cin>>dian>>bian; // 输入点和边
for(int i=1; i<=dian; i++)
for(int j=1; j<=dian; j++)
cin>>ljb[i][j]; // 输入邻接表
// 从点1出发
for(int i=1; i<=dian; i++){
// 相关参数初始化
a[i] = 1;
b[i] = ljb[1][i];
// 目前最小树只有点1,所以最小边集合只能是与点1相连的点
/*
a[1] a[2] a[3] a[4] a[5] a[6]
1 1 1 1 1 1
b[1] b[2] b[3] b[4] b[5] b[6]
0 6 1 5 100 100
*/
}
juge[1] = 0; // 点1进入最小生成树
int t=1;
while(t<dian) // n个点n-1条边
{
int k=1;
for(int i=1; i<=dian; i++){
if(b[i]<b[k])
k = i;
else if(juge[k]==0) // 考虑到(b[i]==0)时的情况
k = i;
}
// 选出最小的那条边b[k],< a[k],k > == b[k];
cout<<b[k]<<" ";
b[k] = 100; // 输出b[k]后,此路就不通了
juge[k] = 0; // 点k进入最小生成树
// 当点k进入最小生成树后,生成树这个大家庭就又刷新了;
// 那么从这个大家庭到其他点的最小边集合可能要更新了
for(int i=1; i<=dian; i++){
if(juge[i]!=0){
if(ljb[k][i]<b[i]){ // ljb[k][?]新成员点k连接的边
b[i] = ljb[k][i];
a[i] = k;
// 如果有新边小于最小边集合{ b[i] },更换;
}
}
}
++t;
}
}