PTA 08-图7 公路村村通

PTA 08-图7 公路村村通

原题链接
现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:
输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。

输出格式:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。

输入样例:
6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3
结尾无空行

输出样例:
12
结尾无空行

思路

(1)如果找cost中找不到最小的->不连通

v=FindMin();//cost中最小的min值的i
if(v==-1){//找不到最小的
    return -1;
}

(2)如果最后结点个数不为N个->不连通

	int cnt=0;
    for(int i=0;i<NumberofVertex;i++){
        if(cost[i]==0){
            cnt++;
        }
    }
    if(cnt<NumberofVertex){
        return -1;//不能构成生成树
    }

Code

#include<iostream>
#define MaxN 1001
#define INIFITE 10001
using namespace std;
int G[MaxN][MaxN];
int cost[MaxN];//记录是否被标记MST和与MST树的距离
int NumberofVertex,NumberofEdge;
void init(){
    for(int i=0;i<NumberofVertex;i++){
        cost[i]=0;//全都离树距离为0
        for(int j=0;j<NumberofVertex;j++){
            if(i!=j){
                G[i][j]=INIFITE;
            }else{
                G[i][j]=0;
            }
        }
    }
}
//在cost中找min值的i
int FindMin(){
    int index=-1,minlen=INIFITE;
    for(int i=0;i<NumberofVertex;i++){
        if(cost[i]!=0&&cost[i]<minlen){
            minlen=cost[i];
            index=i;
        }
    }
    return index;
}
//实现prim算法
int Prim(){
    int sum=0;
    cost[0]=0;//将顶点加入MST树
    //将第一个顶点和相关的边存到dist中
    for(int i=0;i<NumberofVertex;i++){
        if(G[0][i]){//有边
            cost[i]=G[0][i];//存到cost中
        }
    }
    int v;
    for(int i=1;i<NumberofVertex;i++){//还需要找N-1个顶点
        v=FindMin();//cost中最小的min值的i
        if(v==-1){//找不到最小的
            return -1;
        }
        sum+=cost[v];
        cost[v]=0;//加入MST树中
        for(int i=1;i<NumberofVertex;i++){
            if(G[v][i]&&cost[v]+G[v][i]<cost[i]){//相邻结点且花费更小
                cost[i]=cost[v]+G[v][i];
            }
        }
    }
    int cnt=0;
    for(int i=0;i<NumberofVertex;i++){
        if(cost[i]==0){
            cnt++;
        }
    }
    if(cnt<NumberofVertex){
        return -1;//不能构成生成树
    }
    return sum;
}

int main(){
    scanf("%d %d",&NumberofVertex,&NumberofEdge);
    if(NumberofEdge<NumberofVertex-1){//M<N-1
        printf("-1");
        return 0;
    }
    init();
    for(int i=0;i<NumberofEdge;i++){
        int v1,v2,price;
        scanf("%d %d %d",&v1,&v2,&price);
        G[v1-1][v2-1]=G[v2-1][v1-1]=price;
    }
    int res=Prim();
    printf("%d",res);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值