08-图7 公路村村通 (30分)(C语言实现)(数据结构)

2023-11-28 18:48

本文主要是介绍08-图7 公路村村通 (30分)(C语言实现)(数据结构),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

输入格式:
输入数据包括城镇数目正整数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>
#define Max 1000
typedef struct
{int x,y;int cost;
}city;
typedef struct//堆
{city data[3005];int size;
}Minheap;
Minheap minh;
int n,m;
int path[1005];//用来存放父结点的下标(集合操作),每个数组下标存放父亲结点,为根节点则为0

函数的声明

void Kruskal();
city del(Minheap &h);

首先看一下堆的操作

void init(Minheap &h)//初始化堆
{h.size=0;h.data[0].cost=-1;
}
void insert(Minheap &h,city a)//堆的插入操作
{int i=++h.size;//传入一个容量+1for(;i>0&&a.cost<h.data[i/2].cost;i/=2){h.data[i]=h.data[i/2];}h.data[i]=a;
}
city del(Minheap &h)//最小堆中的删除操作
{city min=h.data[1];/*我们是从数组下标为1开始存入数据的,所以此时为最小值*/city last=h.data[h.size--];if(h.size==0) return min;int i=2;for(;i<=h.size;){if(h.data[i].cost>h.data[i+1].cost&&i<h.size)/*在堆中,父结点值肯定比子树要小,但是左右子树就不确定了*/i++;if(h.data[i].cost<last.cost) //从子树找更小的值代替根节点,再从子树的子树找更小的代替子树{h.data[i/2]=h.data[i];i*=2;}else break;}h.data[i/2]=last;return min;
}

判断是否属于一个集合

int judgeroot(city a){while(path[a.x]!=0) {a.x=path[a.x];}         //进行循环,直到找到根while(path[a.y]!=0) {a.y=path[a.y];}if(a.x==a.y) return 0;else {path[a.x]=a.y;return 1;}
}

核心算法

void Kruskal()//算法
{int v=0,mincost=0;while(v!=n-1&&minh.size!=0)//有公路数{city a=del(minh);if(judgeroot(a))//判断是否属于同一个集合,如果属于同一个集合,错误{v++;//连通数加1mincost+=a.cost;//加上这条道路的花费}}	if(v!=n-1)  printf("-1\n");//没有连通,中途操作没有执行完else printf("%d\n",mincost);//打印最小花费
}

主函数

int main(){city a;init(minh);scanf("%d%d",&n,&m);//输入城镇数目和候选道路数for(int i=0;i<m;i++){scanf("%d%d%d",&a.x,&a.y,&a.cost);//输入道路号和代价insert(minh,a);//插入堆中}Kruskal(); //算法
} 

文章总代码如下

#include<stdio.h>
#define Max 1000
typedef struct
{int x,y;int cost;
}city;
typedef struct//堆
{city data[3005];int size;
}Minheap;
Minheap minh;
int n,m;
int path[1005];//用来存放父结点的下标(集合操作)void Kruskal();
city del(Minheap &h);void init(Minheap &h)//初始化堆
{h.size=0;h.data[0].cost=-1;
}
void insert(Minheap &h,city a)//堆的插入操作
{int i=++h.size;//传入一个容量+1for(;i>0&&a.cost<h.data[i/2].cost;i/=2){h.data[i]=h.data[i/2];}h.data[i]=a;
}
int judgeroot(city a){while(path[a.x]!=0) {a.x=path[a.x];}         //进行循环,直到找到根while(path[a.y]!=0) {a.y=path[a.y];}if(a.x==a.y) return 0;else {path[a.x]=a.y;return 1;}
}
void Kruskal()//算法
{int v=0,mincost=0;while(v!=n-1&&minh.size!=0)//有公路数{city a=del(minh);if(judgeroot(a))//判断是否属于同一个集合,如果属于同一个集合,错误{v++;//连通数加1mincost+=a.cost;//加上这条道路的花费}}	if(v!=n-1)  printf("-1\n");//没有连通,中途操作没有执行完else printf("%d\n",mincost);//打印最小花费
}
city del(Minheap &h)//最小堆中的删除操作
{city min=h.data[1];/*我们是从数组下标为1开始存入数据的,所以此时为最小值*/city last=h.data[h.size--];if(h.size==0) return min;int i=2;for(;i<=h.size;){if(h.data[i].cost>h.data[i+1].cost&&i<h.size)/*在堆中,父结点值肯定比子树要小,但是左右子树就不确定了*/i++;if(h.data[i].cost<last.cost) //从子树找更小的值代替根节点,再从子树的子树找更小的代替子树{h.data[i/2]=h.data[i];i*=2;}else break;}h.data[i/2]=last;return min;
}int main(){city a;init(minh);scanf("%d%d",&n,&m);//输入城镇数目和候选道路数for(int i=0;i<m;i++){scanf("%d%d%d",&a.x,&a.y,&a.cost);//输入道路号和代价insert(minh,a);//插入堆中}Kruskal(); //算法
} 

对了还要提一点,在PTA中c可能编译不成功,不知道为啥,有解决办法的同学请教教我,但是用c++编译就可以成功了。

这篇关于08-图7 公路村村通 (30分)(C语言实现)(数据结构)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/430110

相关文章

Python使用python-can实现合并BLF文件

《Python使用python-can实现合并BLF文件》python-can库是Python生态中专注于CAN总线通信与数据处理的强大工具,本文将使用python-can为BLF文件合并提供高效灵活... 目录一、python-can 库:CAN 数据处理的利器二、BLF 文件合并核心代码解析1. 基础合

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

golang版本升级如何实现

《golang版本升级如何实现》:本文主要介绍golang版本升级如何实现问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录golanwww.chinasem.cng版本升级linux上golang版本升级删除golang旧版本安装golang最新版本总结gola

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Mysql实现范围分区表(新增、删除、重组、查看)

《Mysql实现范围分区表(新增、删除、重组、查看)》MySQL分区表的四种类型(范围、哈希、列表、键值),主要介绍了范围分区的创建、查询、添加、删除及重组织操作,具有一定的参考价值,感兴趣的可以了解... 目录一、mysql分区表分类二、范围分区(Range Partitioning1、新建分区表:2、分

MySQL 定时新增分区的实现示例

《MySQL定时新增分区的实现示例》本文主要介绍了通过存储过程和定时任务实现MySQL分区的自动创建,解决大数据量下手动维护的繁琐问题,具有一定的参考价值,感兴趣的可以了解一下... mysql创建好分区之后,有时候会需要自动创建分区。比如,一些表数据量非常大,有些数据是热点数据,按照日期分区MululbU

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

IDEA中新建/切换Git分支的实现步骤

《IDEA中新建/切换Git分支的实现步骤》本文主要介绍了IDEA中新建/切换Git分支的实现步骤,通过菜单创建新分支并选择是否切换,创建后在Git详情或右键Checkout中切换分支,感兴趣的可以了... 前提:项目已被Git托管1、点击上方栏Git->NewBrancjsh...2、输入新的分支的

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os