HOJ 1102 Constructing Roads(最小生成树)

数据量不大,直接暴力过。我用了Prime,过程写在注释中。

#include<iostream>
#include<cstring>
#include<algorithm>
#pragma warning(disable: 4996)
using namespace std;
const int NN = 100 + 5, INF = 99999999;
int a[NN][NN], f[NN];

int find(int x)
{//找到根节点
	if (x == f[x]) return x;
	f[x] = find(f[x]);
	return f[x];
}

int mer(int x, int y)
{
	x = find(x);
	y = find(y);
	if (x != y)
		f[x] = y;//这里是把传入参数x的根节点的父节点改成传入参数y的根节点
	return 1;
}

int main()
{
	int n, q, x, y, sum;
	while (scanf("%d", &n) != EOF)
	{
		sum = 0;
		if (n == 0) break;
		for (int i = 0; i < n; i++)//每个顶点的根节点记录为自己
			f[i] = i;
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
			{
				scanf("%d", &x);
				x == 0 ? a[i][j] = INF : a[i][j] = x;//0的话记录为无穷大
			}
		scanf("%d", &q);
		for (int i = 0; i < q; i++)
		{
			scanf("%d %d", &x, &y);
			mer(x - 1, y - 1);//代码数据记录从0开始,题目从1开始,故需要-1
		}
	while (1)
	{//用Prime算法求解,找到所有边中连接两个不同集合的最小边,然后把这条边的两个顶点连接起来,不断重复直至覆盖所有顶点
		int min0 = INF, flag = 1;
		for (int i = 0; i < n; i++)
			for (int j = 0; j <= i; j++)
				if (find(i) != find(j) && a[i][j] < min0)
				{
					min0 = a[i][j];
					x = i;
					y = j;
					flag = 0;
				}
		if (flag) break;
		mer(x, y);
		sum += min0;
		a[x][y] = INF;
		//a[y][x] = INF;
	}
		cout << sum << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44724908/article/details/104180362