数据结构 08-图7 公路村村通 (30 分)

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

输入格式:

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

 

最小生成树

Prim算法和 Kruskal算法

Prim算法的时间复杂度是O(|V|^2) 不依赖与E,因此边稠密的图使用Prim算法求最小生成(代价)树,不会增加复杂度

Kruskal算法的时间复杂度为O(|E|log|E|) 不依赖于顶点,适合边稀疏的图求最小生成树

本题应使用Prim算法

 

 

 参考文章 https://www.cnblogs.com/wanghao-boke/p/10851398.html

 

维护一个已知的生成树到各邻接点的距离数组 cost  初始值为任意结点到其邻接点的距离,

  进入循环n-1次 表示最小生成树从第一个点开始,再加入n-1个点 完成图的遍历

      每次循环都加入当前未访问过结点中, 最小距离的结点v, 标记访问数组中 v 位置为1, 同时生成树总权值累加cost[v] 的值

      同时检查新加入的结点v到各点的距离是否小于已知 cost数组的距离 , 即 新加入的结点到各邻接点距离 是否小于之前最小生成树到各邻接点的距离, 如果小于已知费用则更新cost数组

      如果循环中没有找到最小邻接结点, 证明不是连通图,退出循环输出-1

  循环结束后输出累加的权值

 

 

#include <iostream>
#include <vector>
using namespace std;
class MatricGraphic{
public:
    vector<vector<int>> vertexs;
    MatricGraphic()=default;
    int minWeightVertex;//记录权值最小的边的顶点
    const int max{9999};
    void build(int n,int m){
        int a,b;
        vertexs=vector<vector<int>>(n,vector<int>(n,9999));
        for(int i=0;i<n;i++){
            vertexs[i][i]=0;
        }
        for(int i=0;i<m;i++){
            scanf("%d %d",&a,&b);
            scanf("%d",&vertexs[a-1][b-1]);
            vertexs[b-1][a-1]=vertexs[a-1][b-1];
        }
    }
    void prim(){
        int n=vertexs.size();
        vector<int> visited(n);
        int weightSum{0};//最小生成树的总权值
//        int u=0;
        visited[0]=1;
        vector<int> cost=vertexs[0];//以第一个点到各点的费用为初始值
        bool flag=true;
        for(int i=0;i<n-1;i++){//迭代n-1次 找到剩下n-1个顶点连接到生成树的最小边
            //如果存在 点 到生成树的边不存在 说明生成树不是全连通
            int min{9999};
            int v{-1};
            for(int j=0;j<n;j++){//找到未访问的邻接点中的最小点v
                if(!visited[j]&&cost[j]<min){
                    v=j;
                    min=cost[j];
                }
            }
            if(v==-1){
                flag=false;
                break;
            }
            visited[v]=1;
            weightSum+=cost[v];
            for(int j=0;j<n;j++){//如果新加入的最小点v到各点j的距离 比 现有的cost数组中对应点j的距离小 则更新最小生成树到各点的已知cost[i]
                if(!visited[j]&&v!=j&&vertexs[v][j]<cost[j]){
                    cost[j]=vertexs[v][j];
                }
            }
        }
        if(flag){
            cout << weightSum<<endl;
        }else{
            cout << "-1"<<endl;
        }
    }
};
int main(){
    int n,m;
    cin >> n >> m;
    MatricGraphic MG;
    MG.build(n, m);
    if(m>=n-1){
        MG.prim();
    }else{
        cout << "-1"<<endl;
    }
    return 0;
}

 

posted @ 2021-05-24 20:32  keiiha  阅读(399)  评论(0编辑  收藏  举报