图结构练习——最小生成树

图结构练习——最小生成树

Time Limit: 1000MS Memory limit: 65536K

题目描述

 有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的。现在我们想知道,最少花多少钱修公路可以将所有的城市连在一起,使在任意一城市出发,可以到达其他任意的城市。
 

输入

 输入包含多组数据,格式如下。
第一行包括两个整数n m,代表城市个数和可以修建的公路个数。(n <= 100, m <=10000)
剩下m行每行3个正整数a b c,代表城市a 和城市b之间可以修建一条公路,代价为c。
 

输出

 每组输出占一行,仅输出最小花费。

示例输入

3 2
1 2 1
1 3 1
1 0

示例输出

2
0

提示

 

来源

 赵利强

示例程序

 
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <queue>
#define inf 999999
using namespace std;

int n, m;
int map[110][110], visit[110], dis[110];

//普里姆算法:首先将所有的边都放到待选区中,也就是dis[], 从顶点开始,遍历这一行也就是两个节点之间最小边,加入到最小生成树中,
//           并把它从待选区中去掉,也就是visit[]赋值为1,遍历所有的节点,根据上一个节点找到的最小边的弧头,再从弧头所在的行开始遍历,直到遍历介结束
void MiniSpanTree(int x)
{
    int k, min, sum = 0;
    visit[0] = 1;                                               //从顶点n开始遍历,遍历就标记为已遍历
    for(int i = 1; i < x; i++)                                  //初始化辅助数组,使每一个辅助数组中存着当前行所有的数据
        dis[i] = map[0][i];
    for(int i = 1; i < x; i++)                                  //对所有的顶点都遍历
    {
        min = inf;                                              //初始化最小值,用来寻找这一行中最小的权值
        for(int j = 0; j < x; j++)                              //遍历此行所有的数据,若数据没有遍历过并且小于最小值,赋值为最小值,并记录下当前的位置,
        {
            if(visit[j] == 0 && min > dis[j])
            {
                min = dis[j];
                k = j;                                          //记录下当前位置,用来寻找下一次要遍历的行
            }
        }
        sum = sum + min;                                        //sum的就是最小生成树的权值
        visit[k] = 1;                                           //标记为已遍历,此列不在遍历
        for(int j = 0; j < x; j++)                              //遍历k行所有的数据,把没有遍历过的并且小于当前值得赋值到辅助数组,也就是待选区中,就是
        {                                                       //就是把当前节点和k节点的所有边的权值放到待选区中,但是只筛选小于当前权值的
            if(visit[j] == 0 && dis[j] > map[k][j])         
                dis[j] = map[k][j];
        }
    }
    cout << sum << endl;
}

int main()
{
    while(cin >> n >> m)
    {
        memset(visit, 0, sizeof(visit));                        //初始化
        memset(map, 0, sizeof(map));
        for(int i = 0; i < n ; i++)                             //初始化邻接矩阵,因为为无向图,以对角线对称,对角线处必定为0,其他位置赋值为无限大
        {
            for(int j = 0; j < n; j++)
            {
                if(i == j)
                    map[i][j] = 0;
                else
                    map[i][j] = inf;
            }
        }
        for(int i = 0; i < m; i++)
        {
            int a, b, c;
            cin >> a >> b >> c;
            if(c < map[a - 1][b - 1])                           //因为数组坐标从0开始,而输出的数据的坐标却是从1开始,将其变化为数组中坐标
                map[a - 1][b - 1] = map[b - 1][a - 1] = c;
        }
        MiniSpanTree(n);
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值