【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;
}
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页