第七章作业2--图的最小生成树 7-2 畅通工程之最低成本建设问题

7-2 畅通工程之最低成本建设问题 (30分)

某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了有可能建设成快速路的若干条道路的成本,求畅通工程需要的最低成本。

输入格式:

输入的第一行给出城镇数目N (1<N≤1000)和候选道路数目M≤3N;随后的M行,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号(从1编号到N)以及该道路改建的预算成本。

输出格式:

输出畅通工程需要的最低成本。如果输入数据不足以保证畅通,则输出“Impossible”。

输入样例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

输出样例1:

12

输入样例2:

5 4
1 2 1
2 3 2
3 1 3
4 5 4

输出样例2:

Impossible

代码仅供参考

Accepted Code

#include<bits/stdc++.h>
using  namespace std;

#define MaxVertexNum 1005
typedef int Vertex; //顶点数据类型
typedef int WeightType;  // 边的权值类型

typedef struct GNode *PtrToGNode;
struct GNode{
    int Nv;  // 顶点数
    int Ne;  // 边数
    WeightType G[MaxVertexNum][MaxVertexNum]; //邻接矩阵
};
typedef PtrToGNode MGraph; //以邻接矩阵存储的图类型

struct {
    Vertex vertex;  //上一个父亲节点的编号
    WeightType type;    //长度
} Closedge[MaxVertexNum];

//标记顶点是否入树
bool Visited[MaxVertexNum];
MGraph CreatG(int, int);

bool Prim(MGraph MG);

int main() {
    int N, M;
    cin >> N >> M;
    MGraph MG = CreatG(N, M);
    Prim(MG);
    return 0;
}

MGraph CreatG(int N, int M) {
    MGraph MGra = new GNode;
    MGra->Nv = N;
    MGra->Ne = M;
    //矩阵下标从0开始
    int a, b, c;
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            MGra->G[i][j] = INT_MAX;
        }
    }
    for (int i = 0; i < MGra->Ne; ++i) {
        cin >> a >> b >> c;
        //创建无向图
        if (MGra->G[a - 1][b - 1] > c) {
            MGra->G[a - 1][b - 1] = c;
            MGra->G[b - 1][a - 1] = c;
        }
    }
    for (int i = 0; i < MaxVertexNum; ++i) {
        Visited[i] = false;
        Closedge[i].type = INT_MAX;
    }
    return MGra;
}
bool Prim(MGraph MG) {
    int sum = 0;
    //辅助数组初始化
    int pos = 0;
    for (int i = pos; i < MG->Nv; ++i) {
        //先把第一个点放到树里
        if (pos != i)  {
            Closedge[i].type = MG->G[pos][i];
            Closedge[i].vertex = pos;
        }
    }
    Closedge[pos].type = 0;
    Visited[pos] = true;

    //选择其他N-1个顶点
    for (int i = 1; i < MG->Nv; ++i) {
        int min = INT_MAX;
        for (int j = 0; j < MG->Nv; ++j) {
            if (!Visited[j] && min > Closedge[j].type) {
                min = Closedge[j].type;
                pos = j;
            }
        }
        if (min == INT_MAX) {
            printf("Impossible");
            return false;
        }
        sum += min;
        Closedge[pos].type = 0;
        Visited[pos] = true;

        //用新加入的点,更新Closedge值
        for (int j = 0; j < MG->Nv; ++j) {
            if (!Visited[j] && Closedge[j].type > MG->G[pos][j]) {
                Closedge[j].type = MG->G[pos][j];
            }
            if (!Visited[j] && Closedge[j].type > MG->G[j][pos]) {
                Closedge[j].type = MG->G[j][pos];
            }
        }
    }
    printf("%d", sum);
    return true;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值