在偏远的山区,水资源很稀缺,因此,我们问每个山区进行打井工程,在不同的地方打了N口井,现在我们要在这N口井之间修建管道,要使得这些井都能连通,同时所使用的管道的长度最小,因此,需要你变成帮助我们实现这一问题。
测试用例:
Input :
2 //case的个数
3
0 1 4
1 0 2
4 2 0
4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0
Output:
Case #1
3
Case #2
28
分析:求图的最小生成树,有一篇文章讲的比较好,http://blog.csdn.net/qjzl2008/article/details/8008077
这里我实现的代码如下:
#include <iostream>
#define MAX 65535
#define MAXVEX 102
using namespace std;
typedef struct
{
int arcs[MAXVEX][MAXVEX];
int vexnum, arcnum;
}MGraph;
void minTree_Prim(MGraph &G, int* minCost, int* addVertex)
{
int lowCost[MAXVEX]; //lowCost数组始终存放索引对应顶点到其他边的最小权值,随时修正权值情况
addVertex[0] = 0; //初始化第一个顶点 addVertext数组索引对应顶点存放边的另一个顶点
lowCost[0] = 0;
minCost[0] = 0;
for (int i = 1; i<G.vexnum; i++)
{
addVertex[i] = 0;
lowCost[i] = G.arcs[0][i];
}
int min = MAX;
for (int i = 1; i<G.vexnum; i++)
{
min = MAX;
int k = 0;
for (int j = 1; j<G.vexnum; j++)
{
if (lowCost[j] && min>lowCost[j]) //lowCost为0时索引值对应顶点已添加到生成树中
{
min = lowCost[j];
k = j;
}
}
//cout << "(" << addVertex[k] << "," << k << ")" << endl; //找出了最小的点
minCost[k] = lowCost[k];
lowCost[k] = 0;
for (int j = 1; j<G.vexnum; j++)
{
if (lowCost[j] && lowCost[j]>G.arcs[k][j]) //修正lowCost数组
{
lowCost[j] = G.arcs[k][j];
addVertex[j] = k;
}
}
}
}
int main()
{
int tc, T;
cin >> T;
for (tc = 1; tc <= T; tc++)
{
int N;
cin >> N;
MGraph myGraph;
int arcs[MAXVEX][MAXVEX] = { 0 };
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
cin >> arcs[i][j];
if (!arcs[i][j])
arcs[i][j] = MAX;
myGraph.arcs[i][j] = arcs[i][j];
//cout << myGraph.arcs[i][j] << " ";
}
//cout << endl;
}
myGraph.vexnum = N;
int* minCost = (int*)malloc(sizeof(int)*MAX);
int* vertexTree = (int*)malloc(sizeof(int)*MAX);
minTree_Prim(myGraph, minCost, vertexTree);
cout << "Case #" << tc << endl;
int count = 0;
for (int i = 0; i < N; i++)
count+= minCost[i];
cout << count << endl;
}
return 0;
}