求解建公路问题

课程设计题目

求解建公路问题


课程设计目的

深入掌握 Prim 和 Kruskal算法在求解实际问题中的应用


问题描述 

        假设有 n 个村庄,编号从到,现在修建一些道路使任意两个村庄之间可以互相连通。所谓两个村庄 A 和B是连通的,指当且仅当A 和 B之间有一条道路或者存在一个村庄 C 使得 A 和C之间有一条道路并且C和B是连通的。有一些村庄之间已经存在一些道路,这里的工作是建造一些道路以使所有村庄都连通,并且所有道路的长度最小。

        测试数据存放在 datal4.txt 文件中,第一行是整数n(3≦n100)它是村庄的数量然后是n 行,其中第行包含 个整数,而这n 个整数中的第个表示村庄与村庄j之间的距离(该距离应为[1,1000]的整数); 然后有一个整数 q(0qn(n+1)/2); 接下来有行,每行包含两个整数a 和b(1 a bn),这意味着已经建立了村庄 a 和村b 之间的道路。例如,data14.txt 的数据如下:

3

0 990 692

990 0 179

692 179 0

1

1 2


源程序

#include <iostream>
#include <cstring>
#include<vector>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXV 105 
int mat[MAXV][MAXV];
int U[MAXV];
int lowcost[MAXV];
int n;

int Prim()									//解法1:Prim算法求顶点1出发的最小生成树的权值和
{	memset(U,0,sizeof(U));
	memset(lowcost,0x3f,sizeof(lowcost));
	int ans=0;								//存放结果
	lowcost[1]=0;
	for(int i=1;i<=n;i++)
	{	int minc=INF,k=0;
		for(int j=1;j<=n;j++)					//在(V-U)中找出离U最近的顶点k
			if(!U[j] && lowcost[j]<minc)
			{	minc=lowcost[j];
				k=j;
			}
		ans+=minc;							//累计最小生成树的边权
		U[k]=1;								//标记k已经加入U
		for(int i=1;i<=n;i++)					//调整
			if(U[i]==0 && lowcost[i]>mat[k][i])
				lowcost[i]=mat[k][i];
	}
	return ans;
}
//----并查集基本运算算法 
int parent[MAXV];							//并查集存储结构
int rnk[MAXV];								//存储结点的秩
void Init(int n)								//并查集初始化
{	for (int i=1;i<=n;i++)						//顶点编号1到n 
	{	parent[i]=i;
		rnk[i]=0;
	}
}
int Find(int x)								//并查集中查找x结点的根结点
{	if (x!=parent[x])
		parent[x]=Find(parent[x]);			//路径压缩
	return parent[x];
}
void Union(int x,int y)						//并查集中x和y的两个集合的合并
{	int rx=Find(x);
	int ry=Find(y);
	if (rx==ry)								//x和y属于同一棵树的情况
		return;
	if (rnk[rx]<rnk[ry])
		parent[rx]=ry;						//rx结点作为ry的孩子 
	else
	{	if (rnk[rx]==rnk[ry])					//秩相同,合并后rx的秩增1
			rnk[rx]++;
		parent[ry]=rx;						//ry结点作为rx的孩子
	}
}
struct Edge								//边向量元素类型
{	int u;									//边的起始顶点
	int v;									//边的终止顶点
	int w;									//边的权值
	Edge(int u,int v,int w)					//构造函数
	{	this->u=u;
		this->v=v;
		this->w=w;
	}
	bool operator<(const Edge &s) const		//重载<运算符
	{
		return w<s.w;						//用于按w递增排序
	}
};
int Kruskal()								//解法2:改进的Kruskal算法求最小生成树的权值和
{	int ans=0;
	vector<Edge> E;							//建立存放所有边的向量E
	for (int i=1;i<=n;i++)						//由图的邻接矩阵g产生边向量E
		for (int j=1;j<=n;j++)
			if (i<j)
				E.push_back(Edge(i,j,mat[i][j]));
	sort(E.begin(),E.end());					//对E按权值递增排序
	Init(n);									//并查集初始化
	int k=1;									//k表示当前构造生成树的第几条边,初值为1
	int j=0;									//E中边的下标,初值为0
	while (k<n)								//生成的边数小于n时循环
	{	int u1=E[j].u;
		int v1=E[j].v;						//取一条边的起始和终止顶点
		int sn1=Find(u1);
		int sn2=Find(v1);					//分别得到两个顶点所属的集合编号
		if (sn1!=sn2)							//两顶点属于不同的集合,该边是最小生成树的一条边
		{	ans+=E[j].w;					//累计最小生成树的边权
			k++;							//生成边数增1
			Union(sn1,sn2);					//合并
		}
		j++;									//扫描下一条边
	}
	return ans;
}
int main()
{
	freopen("data14.txt","r",stdin);	//输入重定向 
	scanf("%d",&n);
	printf("村庄n=%d\n",n);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&mat[i][j]);
	printf("邻接矩阵\n"); 
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
			printf("%4d ",mat[i][j]);
		printf("\n");
	}
	int k;
	scanf("%d",&k);
	printf("已经建好如下%d条道路\n",k);
	for(int i=0;i<k;i++)
	{	int a,b;
		scanf("%d%d",&a,&b);
		printf("  (%d,%d)\n",a,b);
		mat[a][b]=mat[b][a]=0;
	}
	printf("求解结果\n"); 
	printf("  解法1: %d\n",Prim());
	printf("  解法2: %d\n",Kruskal());
	return 0;
}

数据及结果分析

 

求解建公路问题可以使用Prim算法和Kruskal算法。这两种算法都是基于贪心的思想,通过不断选择最小权重的边来构建最小生成树。

1. Prim算法:

   - 数据结构:使用邻接矩阵或邻接表表示图。

   - 算法设计:

     1) 初始化一个空的最小生成树集合M,将起点加入M。

     2) 从M中选取一条权值最小的边(u, v),将v加入M。

     3) 更新与v相邻的未被加入M的顶点的权值,并选取权值最小的边(u, w),将w加入M。

     4) 重复步骤2和3,直到M包含所有顶点。

2. Kruskal算法:

   - 数据结构:使用邻接表表示图。

   - 算法设计:

     1) 将所有边按照权值从小到大排序。

     2) 初始化一个空的最小生成树集合M。

     3) 遍历排序后的边,对于每条边(u, v),如果u和v不在同一个连通分量中,则将边(u, v)加入M,并将u和v所在的连通分量合并。

     4) 重复步骤3,直到M包含所有顶点。

在实际应用中,可以根据具体问题选择合适的算法。例如,如果图是稀疏的,可以使用邻接表表示图,从而减少存储空间和计算时间;如果需要快速找到最小生成树,可以使用Prim算法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/321283.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UG装配-WAVE几何链接器

自上向下&#xff08;自顶向下&#xff09;设计 先将产品主要结构&#xff08;或主要部件&#xff09;建立好&#xff0c;然后再根据要求设计其它组件&#xff0c;使每个组件之间有数据关联&#xff0c;适用于产品开发初期&#xff0c;便于修改&#xff0c;修改组件数据后&…

如何利用小程序介绍公司品牌形象?

企业小程序的建设对于现代企业来说已经成为了一项必不可少的工作。随着移动互联网的快速发展&#xff0c;越来越多的职场人士和创业老板希望通过小程序来提升企业形象&#xff0c;增强与用户的互动&#xff0c;实现更好的商业效果。在这个过程中&#xff0c;使用第三方制作平台…

C-操作符详解

1.进制转换 1.1 10进制转2进制 方法&#xff1a;短除法 1.2 2进制转换8进制 8进制的数字每⼀位是0~7的&#xff0c;0~7的数字&#xff0c;各⾃写成2进制&#xff0c;最多有3个2进制位就⾜够了&#xff0c;⽐如7的⼆进制是111&#xff0c;所以在2进制转8进制数的时候&#xf…

三、Qt Creator 使用

关于Qt的安装及环境配置&#xff0c;在我的上一篇《二、QT下载、安装及问题解决(windows系统)》已经讲过了。 本章节有一个重点&#xff0c;在新建 工程文件时&#xff0c;所在路径不要有中文&#xff0c;否则编译及运行程序不能正常运行。 在使用Qt Creator&#xff08;以下…

A connection was successfully established with the server but then an error

在使用EFCore生成数据库的时候&#xff0c;报上面的错误&#xff01; 解决方法&#xff1a; 加&#xff08;EncryptTrue;TrustServerCertificateTrue;&#xff09;即可&#xff1a; "ConnectionStrings": { "DefaultConnection": "Data SourceLAP…

基于ssm运动器械购物商城+jsp论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本运动器械购物商城就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

MongoDB安装与基本使用

一、简介 1.1 Mongodb 是什么 MongoDB 是一个基于分布式文件存储的数据库&#xff0c;官方地址 https://www.mongodb.com/ 1.2 数据库是什么 数据库&#xff08; DataBase &#xff09;是按照数据结构来组织、存储和管理数据的 应用程序 1.3 数据库的作用 数据库的…

Python基础知识:整理15 列表的sort方法

1 sorted() 方法 之前我们学习过 sorted() 方法&#xff0c;可以对列表、元组、集合及字典进行排序 # 1.列表 ls [1, 10, 8, 4, 5] ls_new sorted(ls, reverseTrue) print(ls_new) …

最新地图下载器(支持切片和矢量数据下载)

一、应用背景 在当今数字时代&#xff0c;地图下载器成为了越来越多人的必备工具。地图下载器可以帮助人们在没有网络的情况下使用地图&#xff0c;也可以帮助人们快速下载大量地图数据&#xff0c;方便日常生活和旅行。本文将介绍地图下载器的基本功能及其在不同场景下的应用。…

JVM运行时数据区(下篇)

紧接上篇&#xff1a;JVM运行时数据区&#xff08;上篇&#xff09;-CSDN博客 堆 一般Java程序中堆内存是空间最大的一块内存区域。创建出来的对象都存在于堆上。 栈上的局部变量表中&#xff0c;可以存放堆上对象的引用。静态变量也可以存放堆对象的引用&#xff0c;通过静态…

TikTok系列算法定位还原x-ss-stub

TikTok的x系列的算法比较有名,很多粉丝也问过,之前没有深入研究,本人工作量也比较大。 我们上次说到TikTok的x-ss-stub的算法就是ccmd5标准库算的,今天要讲细致点,表面这个结论本不是直接将数据md5那么来的,是经过一系列分析来的 上图是上次截图的,这次我们分析整个定位…

PostgreSQL autovacuum详解(自动化清理空间)

文章目录 1. 什么是autovacuum2. autovacuum的作用3. 如何开启autovacuum4. autovacuum相关参数4.1 触发条件4.2 参数建议4.3 更改系统autovacuum相关参数4.4 更改单表autovacuum相关参数 1. 什么是autovacuum PostgreSQL的autovacuum是一种自动化的维护工具&#xff0c;用于管…

Git相关3 —— 命令及添加Gitee的公钥

1.Git相关命令1 -- 工作目录、暂存区、本地仓库、 使用平台有&#xff1a;cmd、Git bash、VSCode window系统修改VSCode默认终端为git bash git init 初始化 --- 新增.git 文件夹 git status 查看 文件/文件夹 状态 git add 需要追踪的文件名/文件夹名 提交到暂存区 git add…

SpringBoot集成Minio

pom文件导入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/P…

kubeadm部署

准备环境 master、node1、node2 关闭SWAP\SELINUX\FIREWALLD\开启网卡转发 配置YUM源 cat <<EOF > /etc/yum.repos.d/kubernetes.repo > [kubernetes] > nameKubernetes > baseurlhttps://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_6…

基于深度学习的多类别电表读数识别方案详解

基于深度学习的多类别电表读数识别方案详解 多类别电表读数识别方案详解项目背景项目难点最终项目方案系列项目全集&#xff1a; 安装说明环境要求 数据集简介数据标注模型选型明确目标&#xff0c;开始下一步的操作 检测模型训练模型评估与推理番外篇&#xff1a;基于目标检测…

C++力扣题目701--二叉搜索树中的插入操作

给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&#xff0c;可能存在多种有效的插入方式&a…

蓝桥杯省赛无忧 STL 课件17 map

01 map 02 multimap 03 unordered_map 04 代码示例

微信商家转账到零钱怎么开通?场景模板

商家转账到零钱是什么&#xff1f; 使用商家转账到零钱这个功能&#xff0c;可以让商户同时向多个用户的零钱转账。商户可以使用这个功能用于费用报销、员工福利发放、合作伙伴货款或分销返佣等场景&#xff0c;提高效率。 商家转账到零钱的使用场景有哪些&#xff1f; 商家…

ES API 批量操作 Bulk API

bulk 是 elasticsearch 提供的一种批量增删改的操作API。 bulk 对 JSON串 有着严格的要求。每个JSON串 不能换行 &#xff0c;只能放在同一行&#xff0c;同时&#xff0c; 相邻的JSON串之间必须要有换行 &#xff08;Linux下是\n&#xff1b;Window下是\r\n&#xff09;。bul…
最新文章