打井问题

在偏远的山区,水资源很稀缺,因此,我们问每个山区进行打井工程,在不同的地方打了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;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值