【2020年天梯赛校选赛】7-15 公路村村通

【2020年天梯赛校选赛】7-15 公路村村通

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

输入格式:
输入数据包括城镇数目正整数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 MaxVertexNum 1003
#define INFINITY     65536
int MGraph[MaxVertexNum][MaxVertexNum];
int dist[MaxVertexNum] = {INFINITY};
int parent[MaxVertexNum] = {0}; /* 如果需要输出联通路径,这里不需要,可无视 */

int FindMinDist(int Nv)
{   /* 寻找未被收录的当前最短路径的顶点下标 */
    int MinDist = INFINITY, V, Min;
    for (V = 1; V <= Nv; V++)
    {   
        if (dist[V] != 0 && dist[V] < MinDist)
        {   /* 如果节点V未被收录(为0表示被收录)并且小于最短距离 */
            MinDist = dist[V];  // 更新最短距离
            Min = V;        // 设置V的父亲结点为0
        }
    }
    if (MinDist < INFINITY)
        return Min; // 如果找到返回顶点下标
    else
        return 0;
}

int Prim(int Nv)
{
    int TotalCost = 0, Vcount = 0, V, W;
    for (V = 1; V <= Nv; V++)
    {   /* 初始化dist,并设置所有结点的父节点为1 */
        dist[V] = MGraph[1][V];
        parent[V] = 1;
    }
    /* 把1点收入 */
    dist[1] = 0;
    parent[1] = -1;
    Vcount++;

    while (1)
    {
        V = FindMinDist(Nv);
        if (!V)
            break;
        Vcount++;
        TotalCost += dist[V];
        dist[V] = 0;    // 把V点收录进来
        for (W = 1; W <= Nv; W++)
        {
            if (dist[W] != 0 && MGraph[V][W] < dist[W])
            {   /* 如果W未被收录 并且V<->W之间的距离变小 */
                dist[W] = MGraph[V][W];
                parent[W] = V;
            }
        }
    }
    if (Vcount == Nv)   // 如果最小生成树的边数正好为Nv-1
        return TotalCost;
    else    // 反之,无法构成最小生成树
        return -1;
}

int main(int argc, char const *argv[])
{
    int N, M, v, w, cost, MinCost;
    scanf("%d %d", &N, &M);
    /* 初始化图 */
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= N; j++)
            MGraph[i][j] = INFINITY;
    /* 输入图信息并更新图 */
    for (int i = 1; i <= M; i++)
    {
        scanf("%d %d %d", &v, &w, &cost);
        MGraph[v][w] = cost;
        MGraph[w][v] = cost;
    }
    MinCost = Prim(N);      
    printf("%d\n", MinCost);    // 输出结果

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值