PTA 08-图7 公路村村通 (30point(s)) c语言实现

11 篇文章 1 订阅

公路村村通

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

输入格式:
输入数据包括城镇数目正整数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

具体思路

最小生成树的生成,普利姆算法,还可以用另一种,都一样简单

具体代码

#include<stdio.h>
#include<stdlib.h>
#define MAX 1000
#define BKD 65535
#define ERROR -1
#define false -1
#define true 1
typedef struct node *Post;
struct node
{
    int ding;
    int bian;
    int m[MAX][MAX];
};
typedef Post Mgraph;/*邻接矩阵储存图*/
int dist[MAX];/*普利姆算法的储存数组*/
int dao=0;/*纳入最小生成树的顶点个数*/
Mgraph JIANtu()/*建图*/
{
    Mgraph M;
    M=(Mgraph)malloc(sizeof(struct node));
    int b,d,i,j,zh,a;
    scanf("%d",&M->ding);
    for( i=0;i<M->ding;i++)
        for( j=0;j<M->ding;j++)
        {
            M->m[i][j]=BKD;/*边的初始化要为足够大的数*/
        }
    scanf("%d",&M->bian);
    for(i=0;i<M->bian;i++)
    {
        scanf("%d %d %d",&b,&d,&zh);
        M->m[b-1][d-1]=zh;/*无向图*/
        M->m[d-1][b-1]=zh;
    }
    return M;
}
int Findmin(Mgraph M,int dist[])/*类似迪杰斯特拉算法的找出,dist值最小的哪一个。但是有点出入,直接用dist来标记是否访问*/
{
    int mv,i;
    int md=BKD;
    for(i=0;i<M->ding;i++)
    {
        if(dist[i]!=0&&dist[i]<md)
        {
            md=dist[i];
            mv=i;
        }
    }
    if(md<BKD)
    {
        return mv;
    }
    else
        return ERROR;
}
int Prim(Mgraph M)/*普利姆算法,返回最小生成树的总权重*/
{
    int i,j,k;
    int qi=0;
    for(i=0;i<M->ding;i++)
    {

        
        if(M->m[0][i]<BKD)/*一般都是从0这个顶点开始的,从其他点,可以更换*/
            dist[i]=M->m[0][i];/*初始这个dist数组*/
        else
            dist[i]=BKD;
    }
    dao++;/*起点进去了,加一*/
    dist[0]=0;/*变为0,标识已经纳入最小生成树中了*/
    while(1)
    {
        i=Findmin(M,dist);
        if(i==ERROR)/*找不出来就结束循环了*/
            break;
        dao++;/*找出来一个,顶点个数就加一*/
        qi+=dist[i];/*计算权重*/
        dist[i]=0;/*标记已经访问*/
        for(j=0;j<M->ding;j++)/*替换,找到可以到的路径,就标识出来长度*/
        {
            if(dist[j]!=0&&M->m[i][j]<BKD)/*必须是没用访问过的顶点*/
            {
                if(M->m[i][j]<dist[j])
                {
                  dist[j]=M->m[i][j];

                }
            }
        }
    }
    return qi;
}
int main()
{
    Mgraph M;
    M=JIANtu();
    int k;
    k=Prim(M);
    if(dao!=M->ding)/*当进入最小生成树的顶点个数不等于图的顶点数时,说明图不连通*/
        printf("-1");
    else
        printf("%d",k);
}

具体结果在这里插入图片描述

代码很基础,有错请指出,一起进步,谢谢!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值