Hdu-3371 Connect the Cities

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3371

题目大意:给你很多条边,包括顶点和权值。再给你一些点,表示这些点已经有图连通,求最小生成树的权值之和。

解题思路:

将后来的连通的边的权值设定为0就可以了。就是比较裸的最小生成树。。。但是细节处理比较麻烦,我就是处理后来那些连通顶点花了很长时间,而且是卡过去了。。题目要求1s。我968ms。看来需要优化。。。。。。。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 510

int map[MAXN][MAXN], lowcost[MAXN];
bool visit[MAXN];
int alr[MAXN];
int num, sum;

void prim()
{
	int temp, k;
	memset(visit, false, sizeof(visit));
	for(int i = 1; i <= num; ++i)
		lowcost[i] = map[1][i];
	sum = 0;
	visit[1] = true;
	for(int i = 1; i <= num; ++i)
	{
		temp = INF;
		for(int j = 1; j <= num; ++j)
			if(!visit[j] && temp > lowcost[j])
				temp = lowcost[k = j];
		if(temp == INF)
			break;
		visit[k] = 1;
		sum += temp;
		for(int j = 1; j <= num; ++j)
			if(!visit[j] && lowcost[j] > map[k][j])
				lowcost[j] = map[k][j];
	}
}

int main()
{
	int ncase;
	int road, already;
	int a, b, cost;
	int nodenum, node;
	bool flag;
	scanf("%d", &ncase);
	while(ncase--)
	{
		flag = true;
		memset(alr, INF, sizeof(alr));
		memset(map, INF, sizeof(map));
		scanf("%d%d%d", &num, &road, &already);
		for(int i = 1; i <= road; ++i)
		{
			scanf("%d%d%d", &a, &b, &cost);
			if(cost < map[a][b])
				map[a][b] = map[b][a] = cost;
		}
		for(int i = 1; i <= already; ++i) //处理这些权值为0的边
		{
			scanf("%d", &nodenum);
			for(int j = 1; j <= nodenum; ++j)
				scanf("%d", &alr[j]);
			int k;
			for(int j = 1; j < nodenum; ++j)
			{
				k = j + 1;
				map[alr[j]][alr[k]] = map[alr[k]][alr[j]] = 0;
			}
		}
		prim();
		for(int i = 1; i <= num; ++i) //判断图的连通性
			if(visit[i] == false)
				flag = false;
		if(flag)
			printf("%d\n", sum);
		else
			printf("-1\n");
	}
	return 0;
}


你可能感兴趣的:(优化)