以下测试数据所用的图为:
#include <iostream>
using namespace std;
//Prim算法
//朴素版本
/*
key[所有] = INF;done[所有] = false;par[i] = -1;
根据指定树根r,设置key[r] = 0;
执行n次
{
选择key[]最小的一个点,记录为x
done[x] = true
对于所有x可达的点,更新它们key[]及par[];
}
*/
//高级版本
/*
选择key[]最小的一个点,一般用堆实现的优先队列来实现——
不用执行n次,换成while(优先队列非空),之前先把树根或者全部结点放入优先队列
while (!q.empty())
{
对于出队的结点x,done[x] = ture; 更新所有与x相邻结点的key[]和par[],若有更新则把结点放入队列
//但是这样同一个结点可能被多次放入队列,没关系,优先队列会选出同一个结点中更优的那个结点(也就是最后放入的)
//而处理了这个结点则会标记done[]为true,对于选出来的结点若是done=true(即纳入MST集合)的结点则忽略
//注意这个忽略操作要在标记操作之前!否则都会被忽略掉。
}
*/
//朴素版本实现
//读入一个邻接矩阵
const int N = 110;
const int INF = 999999999;
const int NUL = -1;
int key[N]; //类似dijkstra中的d
int par[N]; //记录父母结点
bool done[N];
int w[N][N];
struct MST{
int from, to;
int weight;
};
MST mst[N];
char trans(int i)
{
return i+'A';
}
int main()
{
int n, min, weight_sum, x, cnt = 0;
cin >> n;
for (int i = 0; i != n; i++) {
for (int j = 0; j != n; j++) {
cin >> w[i][j];
}
}
memset(done, false, sizeof (done));
for (int i = 0; i != n; i++) {
key[i] = INF;
par[i] = NUL;
}
//假定MST(最小生成树)树根选结点0
int root = 0;
key[root] = 0;
//循环n次
for (int k = 0; k != n; k++) {
min = INF;
for (int i = 0; i != n; i++) {
if (!done[i] && key[i] < min) {
min = key[i];
x = i;
}
}
done[x] = true;
//存入MST
if (x != root) {
mst[cnt].from = par[x];
mst[cnt].to = x;
mst[cnt].weight = w[par[x]][x];
weight_sum += mst[cnt].weight;
cnt++;
}
for (int y = 0; y != n; y++) {
if (w[x][y] != 0 && key[y] > w[x][y]) {
key[y] = w[x][y];
par[y] = x; //par[y]指向来源即父母
}
}
} //循环n次
//输出MST
for (int i = 0; i != n-1; i++) {
cout << trans(mst[i].from) << "->" << trans(mst[i].to)
<< " " << "weight = " << mst[i].weight << endl;
}
cout << "weight_sum = " << weight_sum << endl;
return 0;
}
/*
参考数据
图片参考百度百度kruskal的图片
矩阵
7
0 7 0 5 0 0 0
7 0 8 9 7 0 0
0 8 0 0 5 0 0
5 9 0 0 15 6 0
0 7 5 15 0 8 9
0 0 0 6 8 0 11
0 0 0 0 9 11 0
输出:
A->D weight = 5
D->F weight = 6
A->B weight = 7
B->E weight = 7
E->C weight = 5
E->G weight = 9
weight_sum = 39
*/
同样,为了验证代码的正确性,可以测试一下 hdoj1162
AC代码:
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
const int N = 110;
const double INF = 999999999.0;
const int NUL = -1;
double X[N];
double Y[N];
double key[N]; //类似dijkstra中的d
int par[N]; //记录父母结点
bool done[N];
double w[N][N];
inline double dist(double x1, double x2, double y1, double y2)
{
return sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) );
}
int main()
{
int n;
while (cin >> n) {
int min, x, cnt = 0;
double weight_sum = 0.0;
//转为邻接矩阵
for (int i = 0; i != n; i++) {
cin >> X[i] >> Y[i];
}
for (int i = 0; i != n; i++) {
for (int j = 0; j != n; j++) {
if (i == j)
w[i][j] = 0.0;
else {
w[i][j] = dist(X[i], X[j], Y[i], Y[j]);
w[j][i] = w[i][j];
}
}
}
memset(done, false, sizeof (done));
for (int i = 0; i != n; i++) {
key[i] = INF;
par[i] = NUL;
}
//假定MST(最小生成树)树根选结点0
int root = 0;
key[root] = 0;
//循环n次
for (int k = 0; k != n; k++) {
min = INF;
for (int i = 0; i != n; i++) {
if (!done[i] && key[i] < min) {
min = key[i];
x = i;
}
}
done[x] = true;
//计算MST的权和
if (x != root) {
weight_sum += w[par[x]][x];
}
for (int y = 0; y != n; y++) {
if (w[x][y] != 0 && key[y] > w[x][y]) {
key[y] = w[x][y];
par[y] = x; //par[y]指向来源即父母
}
}
} //循环n次
printf("%.2lf\n", weight_sum);
}
return 0;
}