最小生成树算法的实现c++

最小生成树算法的实现c++

题目链接:1584. 连接所有点的最小费用 - 力扣(LeetCode)

主要思路:使用krusal算法,将边的权值进行排序(从小到大排序),每次将权值最小且未加入到连通分量中的值给加入其中。主要需要使用并查集,检查是否在同一个连通分量当中。

class Solution {
public:typedef struct edge{int id; //表示这个点int to; //表示要到达的点int weight;//权重bool operator<(edge a) const{return a.weight>weight;}}edge;int calcute(vector<int> point1,vector<int> point2){return abs(point1[0]-point2[0])+abs(point1[1]-point2[1]);}int find(int u,vector<int>& parents){if(parents[u]==u){return u;}else{return find(parents[u],parents);}}int find(int u,vector<int>& parents)  //路径压缩后的{while(u!=parents[u]){parents[u]=parents[parents[u]];u=parents[u];}return u;}/*bool is_same_parent(int u,int v){if(find(u)==find(v)){return true;}return false;}*/int minCostConnectPoints(vector<vector<int>>& points) {int n=points.size();vector<edge> edges;// vector<bool> is_valid(n,false);vector<int> parents(n,0);for(int i=0;i<n;i++){parents[i]=i;}for(int i=0;i<n;i++){for(int j=i+1;j<n;j++){edge temp1;temp1.id=i;temp1.to=j;temp1.weight=calcute(points[i],points[j]);//  edge temp2;//  temp2=temp1;//  temp2.id=temp1.to;//  temp2.to = temp1.id;edges.push_back(temp1);//  edges.push_back(temp2);}}sort(edges.begin(),edges.end());int count=0;int ans=0;// is_valid[edges[0].id]=true;for(int i=0;i<edges.size();i++){int parent1=find(edges[i].id,parents);int parent2=find(edges[i].to,parents);if(parent1!=parent2){parents[parent2]=parent1;cout<<"取边"<<edges[i].id<<"-"<<edges[i].to<<"权重为:"<<edges[i].weight<<endl;ans+=edges[i].weight;count++;}if(count==n){break;}}return ans;/*for(int i=0;i<edges.size();i++){cout<<"本点:"<<edges[i].id<<"要到达的点:"<<edges[i].to<<"权重为:"<<edges[i].weight<<endl;}return 0;*/}
};

使用prime算法做最小生成树

首先要了解什么是链式前向星

前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序,

并记录下以某个点为起点的所有边在数组中的起始位置和存储长度,那么前向星就构造好了.

用len[i]来记录所有以i为起点的边在数组中的存储长度.

用head[i]记录以i为边集在数组中的第一个存储位置.
在这里插入图片描述

在这里插入图片描述

image-20240415105500306

用链式前向星可以避开排序,建立边结构体

struct Edge{int next;int to; //edge[i].to表示第i条边的重点,edge[i].next表示与第i条边同起点的下一条边的存储位置int weight;//边的权值
}
另外还有一个数组head[],它是用来表示以i为起点的第一条边存储的位置,实际上你会发现这里的第一条边存储的位置其实在以i为起点的所有边的最后输入的那个编号.
加边函数为void add(int u,int v,int w)
{edge[cnt].w = w;edge[cnt].to = v;edge[cnt].next = head[u];head[u] = cnt++;
}

在这里插入图片描述
在这里插入图片描述

#include <bits/stdc++.h>
#define INF 0x7f7ff
using namespace std;
int k; //默认初始为0
int head[5010];//由于节点最多为5000个,初始化nodes[i]=0,node[i]表示以第i个节点为起始点第一次出现的位置
struct node{int to;int weight;int next;
}edges[400010];//由于是无向图,要开两倍数组
int n,m;
int ans;
bool vis[5010];//代表该节点是否被访问
int dist[5010];//dis[i]表示已经加入到最小生成树的点到没有加入的点的最短距离
void add(int u,int to,int weight) //实际是逆序的,但不影响结果的正确性,在此使用的是链式前向星,不理解链式前向星的去搜一下前向星相关内容
{edges[++k].to= to;edges[k].weight=weight;edges[k].next = head[u];head[u]=k;
}
void prime()
{fill(dist+1,dist+n+1,INF);dist[1]=0;//选择起点为1for(int i=1;i<=n;i++){int u=-1,minn=INF;for(int j=1;j<=n;j++){if(dist[j]<minn&&!vis[j]) //将距离进行更改,且该点要未被访问{u=j;minn=dist[j]; //更新min值}}if(u==-1){ans=-1;return;}vis[u]=true;ans+=dist[u];for(int j=head[u];j;j=edges[j].next){int v=edges[j].to;if(!vis[v]&&dist[v]>edges[j].weight) dist[v]=edges[j].weight;}}
}
int main()
{cin>>n>>m;for(int i=0;i<m;i++) //建立{int from,to,weight;cin>>from>>to>>weight;add(from,to,weight);add(to,from,weight);}prime();if(ans==-1){cout<<"orz"<<endl;}else{cout<<ans<<endl;}//cout<<edges[0].from<<"-"<<edges[0].to<<"-"<<edges[0].weight<<endl;//cout<<edges[1].from<<"-"<<edges[1].to<<"-"<<edges[1].weight<<endl;// 请在此输入您的代码return 0;
}

由于每次枚举dist比较花费时间,因此可以对其进行优化,使用priority_queue来找最短的距离

struct p
{int id,d;bool operator < (const p &a) const{return a.d<d;}
};
void Prime()
{fill(dist+1,dist+1+n,INF);priority_queue<p> q;p now;now.id=1;now.d=dist[1]=0;q.push(now);while(!q.empty()){p now=q.top();q.pop();int u=now.id;if(now.d!=dist[u]) continue;vis[u]=1;ans+=dist[u];tot++;for(int i=head[u];i;i=edge[i].next){int v=edge[i].to;if(!vis[v]&&dist[v]>edge[i].w){dist[v]=edge[i].w;p nxt;nxt.d=dist[v];nxt.id=v;q.push(nxt);}}}if(tot<n) ans=-1;
}
  if(!vis[v]&&dist[v]>edge[i].w){dist[v]=edge[i].w;p nxt;nxt.d=dist[v];nxt.id=v;q.push(nxt);}}
}
if(tot<n) ans=-1;

}


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux下SPI设备驱动实验:向SPI驱动框架中加入字符设备驱动框架代码

一. 简介 前一篇文章编写了SPI设备驱动框架代码&#xff0c;文章如下&#xff1a; Linux下SPI设备驱动实验&#xff1a;SPI设备驱动框架编写-CSDN博客 本文继续SPI驱动代码的编写。向SPI驱动框架中加入字符设备驱动框架代码。 二. 向SPI驱动框架中加入字符设备驱动框架代码…

Cesium中实现镜头光晕

镜头光晕 镜头光晕 (Lens Flares) 是模拟相机镜头内的折射光线的效果&#xff0c;主要作用就是让太阳光/其他光源更加真实&#xff0c;和为您的场景多增添一些气氛。 Cesium 中实现 其实 Cesium 里面也是有实现一个镜头光晕效果的&#xff0c;添加方式如下&#xff0c;只是效…

Python教学入门:数字类型与字符串

字符串元素组成的序列 字符串元素组成的序列指的是字符串中的每个字符按照一定的顺序排列形成的序列。在 Python 中&#xff0c;字符串是由字符组成的有序序列&#xff08;Sequence&#xff09;&#xff0c;每个字符在字符串中有其固定的位置&#xff08;索引&#xff09;&…

Android RecyclerView的LayoutManager配置

RecyclerView的item布局方式依赖于其配置的布局管理器。不同的布局管理器可以实现不同的界面效果。 LayoutManager介绍 RecyclerView可以通过setLayoutManager设置布局管理器&#xff0c;该方法的源码如下&#xff1a; /*** Set the {link LayoutManager} that this RecyclerV…

java网络编程 BufferedReader的readLine方法读不到数据且一直阻塞

最近在整理Java IO相关内容&#xff0c;会遇到一些以前没有注意的问题&#xff0c;特此记录&#xff0c;以供自查和交流。 需求&#xff1a; 基于Java的BIO API&#xff0c;实现简单的客户端和服务端通信模型&#xff0c;客户端使用BufferedReader的readLine方法读取System.i…

7、docker 集群

docker集群 1、docker file参数设置 2、docker composeCompose和Docker兼容性常用参数Docker-compose.yml配置文件Docker-compose命令大全compose常用调试命令compose文件格式示例应用python flask-rediscpu和gpu配置 附件参考&#xff1a; 1、docker file 参考&#xff1a;ht…

ASPICE 追溯性实践分享

01前言 接着之前的分享&#xff0c;遗留的追溯性ASPICE 认证实践及个人理解分享-CSDN博客文章浏览阅读961次&#xff0c;点赞22次&#xff0c;收藏17次。ASPICE是Automotive 和SPICE的组合&#xff0c;全英文为&#xff08;Automotive Software ProcessImprovement and Determ…

树的遍历算法题总结(第二十六天)

144. 二叉树的前序遍历 题目 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 答案 class Solution {List<Integer> res new ArrayList(); public List<Integer> preorderTraversal(TreeNode root) {deal(root);return res;}void deal(TreeN…

C++修炼之路之继承<二>

目录 一&#xff1a;子类的六大默认成员函数 二&#xff1a;继承与友元 三&#xff1a;继承与静态成员 四&#xff1a;复杂的继承关系菱形继承菱形虚拟继承 1.单继承 2.多继承 3.菱形继承&#xff1b;一种特殊的多继承 4.菱形虚拟继承 5.虚拟继承解决数据冗余和二…

华为OD-C卷-内存冷热标记[100分]C++-100%

题目描述 现代计算机系统中通常存在多级的存储设备,针对海量 workload 的优化的一种思路是将热点内存页优先放到快速存储层级,这就需要对内存页进行冷热标记。 一种典型的方案是基于内存页的访问频次进行标记,如果统计窗口内访问次数大于等于设定阈值,则认为是热内存页,…

小程序 前端如何用wx.request获取 access_token接口调用凭据

在微信小程序中,获取access_token通常是通过wx.request方法来实现的。以下是一个简单的示例代码: 1.获取小程序的appID 与 secret(小程序密钥) 登录之后,请点击左侧的"开发管理"==>点击"开发设置" 就可以找到 2. 在javascript 中的代码: // 定…

【大模型完全入门手册】——大模型入门理论(基于Transformer的预训练语言模型)

博主作为一名大模型开发算法工程师,很希望能够将所学到的以及实践中感悟到的内容梳理成为书籍。作为先导,以专栏的形式先整理内容,后续进行不断更新完善。希望能够构建起从理论到实践的全流程体系。 助力更多的人了解大模型,接触大模型,一起感受AI的魅力! Transformer架构…

性能优化工具

CPU 优化的各类工具 network netperf 服务端&#xff1a; $ netserver Starting netserver with host IN(6)ADDR_ANY port 12865 and family AF_UNSPEC$ cat netperf.sh #!/bin/bash count$1 for ((i1;i<count;i)) doecho "Instance:$i-------"# 下方命令可以…

Rust 语言使用 SQLite 数据库

SQLite 是一种广泛使用的轻量级数据库&#xff0c;它通过简单的文件来承载数据&#xff0c;无需复杂的服务器配置。正因如此&#xff0c;它成为了许多桌面和移动应用的首选数据库。在 Rust 生态中&#xff0c;rusqlite 库为开发者提供了操作 SQLite 数据库的简洁且有效的方法。…

如何用Redis高效实现12306的复杂售票业务

12306的售票业务是一个复杂的系统&#xff0c;需要考虑高并发、高可用、数据一致性等问题。使用Redis作为缓存和持久化存储&#xff0c;可以提高系统的性能和可扩展性&#xff0c;以下是一些可能的实现方式&#xff1a; 1 票源信息缓存&#xff1a;将票源信息&#xff08;如车次…

算法刷题记录2

4.图 4.1.被围绕的区域 思路&#xff1a;图中只有与边界上联通的O才不算是被X包围。因此本题就是从边界上的O开始递归&#xff0c;找与边界O联通的O&#xff0c;并标记为#&#xff08;代表已遍历&#xff09;&#xff0c;最后图中剩下的O就是&#xff1a;被X包围的O。图中所有…

SQC、SQA

QC 品质控制/质量控制&#xff08;QC即英文Quality Control的简称&#xff0c;中文意义是品质控制&#xff09;其在ISO8402&#xff1a;1994的定义是“为达到品质要求所采取的作业技术和活动”。有些推行ISO9000的组织会设置这样一个部门或岗位&#xff0c;负责ISO9000标准所要…

Spring Boot 中 Controller 接口参数注解全攻略与实战案例详解

引言 在 Spring Boot 应用程序中&#xff0c;Controller 是 MVC 架构模式中的核心组件之一&#xff0c;负责处理 HTTP 请求并返回响应结果。为了更好地映射请求、解析请求参数、执行业务逻辑和生成视图或 JSON 数据&#xff0c;Controller 中广泛使用了各种注解。本文将全面梳…

温湿度传感器(DHT11)以及光照强度传感器(BH1750)的使用

前言 对于一些单片机类的环境检测或者智能家居小项目中&#xff0c;温湿度传感器&#xff08;DHT11&#xff09;以及光照强度传感器&#xff08;BH1750&#xff09;往往是必不可少的两个外设&#xff0c;下面我们来剖析这两个外设的原理&#xff0c;以及使用。 1. 温湿度传感…

C语言中,__attribute__关键字

在C语言中&#xff0c;__attribute__是一种特殊的关键字&#xff0c;用于提供关于变量、函数或类型的附加信息。这些信息可以用于编译器优化、代码检查或其他目的。 以下是一些常见的C语言attribute及其用法&#xff1a; 1. __attribute__((const))&#xff1a;表示一个变量的…