hdu 3371 最小生成树 prim

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值