题目链接: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;
}