http://acm.hdu.edu.cn/showproblem.php?pid=3371
题目大意:告诉你有几座城市,再告诉你哪两座城市之间建路要多少钱,在给你哪几个城市之间已经有路,不需要再建。要求的是要使所有城市之间连通最小要花费多少钱。
这里我用了prim算法。。保存城市之间的权值,对于已经建好的城市,将他们的权值赋为0。还有就是要判断是否能找出最小生成树,如果不可以就输出-1,如果在遍历点的时候,并不能找出一个最小的边,那么肯定就是没有最小生成树。(注意要在每个kase开始的时候将所有的边都初始化为INF)。
贡献了好几次WA。。。因为脑残的在每个kase里面也打了一个while,一直退不出来。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define M 1009
#define INF 0x3f3f3f3f
int dis[M];
int map[M][M];
bool vis[M];
int n;
int ans;
int city[M];
bool prim()
{
for(int i = 1;i <= n;i++)
dis[i] = map[1][i];
vis[1] = true;
for(int i = 2;i <= n;i++)
{
int min = INF;
int k;
for(int j = 1;j <= n;j++)
{
if(!vis[j] && dis[j]<min)
{
min = dis[j];
k = j;
}
}
if(min==INF) return false; //判断是否有这个最小生成树,如果找不出这个最小边就意味着没有
ans += min;
vis[k] = true;
for(int j = 1;j <= n;j++)
{
if(!vis[j] && dis[j]>map[k][j])
{
dis[j] = map[k][j];
}
}
}
return true;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans = 0;
memset(vis,0,sizeof(vis));
memset(city,0,sizeof(city));
int m,k;
scanf("%d%d%d",&n,&m,&k); //一开始打成while(scanf(...)) 被反馈一个WA 找了好久
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++)
{
map[i][j] = INF;
map[j][i] = INF;
}
for(int i = 1;i <= m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(map[a][b]>c)
map[a][b] = map[b][a] = c;
}
for(int i = 1;i <= k;i++)
{
int temp;
scanf("%d",&temp);
for(int i = 1;i <= temp;i++)
scanf("%d",&city[i]);//保存已经连通的城市
for(int i = 1;i <= temp;i++)
for(int j = i+1;j <= temp;j++)
{
int a = city[i],b = city[j];
map[a][b] = 0;
map[b][a] = 0;
}
}
bool ok = prim();
if(!ok)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}