最小生成树算法的实现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;//选择起点为1
    for(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;

}


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

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

相关文章

6、Lagent AgentLego 智能体应用搭建(homework)

基础作业 完成 Lagent Web Demo 使用&#xff0c;并在作业中上传截图。文档可见 Lagent Web Demo 0 环境准备 conda create -n agent conda activate agent conda install python3.10 conda install pytorch2.1.2 torchvision0.16.2 torchaudio2.1.2 pytorch-cuda11.8 -c py…

【Linux】动态扩容根目录

Linux&#xff1a;解决centos-root 根目录磁盘空间不足&#xff0c;动态扩容&#xff0c;不删数据 默认安装的root分区只有50G&#xff0c;/home分区有大几百G&#xff0c;可以考虑重新挂载分配空间&#xff0c;不用删除数据&#xff0c;不需要停业务。 查看系统空间 df -h解…

【PDF技巧】PDF文件带有密码,该如何解密?

PDF文件带有打开密码、限制编辑&#xff0c;这两种密码设置了之后如何解密&#xff1f; 不管是打开密码或者是限制编辑&#xff0c;在知道密码的情况下&#xff0c;解密PDF密码&#xff0c;我们只需要在PDF编辑器中打开文件 – 属性 – 安全&#xff0c;将权限状态修改为无保护…

深入理解C语言结构体和位域

目录标题 1. **结构体基础**2. **结构体的定义和使用**3. **结构体内存布局**4. **结构体与函数**5. **位域的定义和使用**6. **位域的实际应用**7. **结构体与位域的混合使用**8. **注意事项和最佳实践**9. **结语** C语言中的结构体和位域是存储和管理数据的重要工具&#xf…

孟德尔随机化(三)—— 再也不用担心网络或其他各种报错啦 | 从数据库下载数据到本地的数据处理方法

前几天咱们分享了看完不会来揍我 | 孟德尔随机化万字长文详解&#xff08;二&#xff09;—— 代码实操 | 附代码注释 结果解读&#xff0c;很多小伙伴们反映在使用代码下载数据时会遇到各种网络或其他报错问题&#xff0c;令人头大的那种&#xff01;不要慌&#xff01;从数据…

每日一题---合并两个有序数组

文章目录 1.前言2.题目2,代码思路3.参考代码 1.前言 上次我们做了移除元素这道题&#xff0c;下来我们看一下合并两个有序数组 2.题目 2,代码思路 创建三个变量&#xff0c;创建三个变量&#xff0c;分别是n1&#xff0c;n2&#xff0c;n3&#xff0c;分别指向nums1[m-1],nums…

华为ensp中Hybrid接口原理和配置命令

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月19日14点03分 Hybrid接口是ENSP虚拟化中的一种重要技术&#xff0c;它既可以连接普通终端的接入链路&#xff0c;又可以连接交换机间的干道链路。Hybrid接口允许多…

排序算法。

***冒泡排序: 基本&#xff1a; private static void sort(int[] a){for (int i 0; i < a.length-1; i) {for (int j 0; j < a.length-i-1; j) {if (a[j]>a[j1]){swap(a,j,j1);}}}} private static void swap(int[] a,int i,int j){int tempa[i];a[i]a[j];a[j]temp…

【YOLOv5】使用yolov5训练模型时报错合集

文章目录 前言问题1 -- VsCode终端无法进入Anaconda创建的虚拟环境【问题描述】【问题分析】【解决方式】方法一方法二 问题2 -- 怎么在VsCode中为项目配置Anaconda创建的虚拟环境【问题描述】【解决方式】 问题3 -- yolov5训练模型时报错RuntimeError: result type Float cant…

代码随想录-算法训练营day12【休息,复习与总结】

代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客 ● day 12 周日休息&#xff08;4.14&#xff09; 目录 复习与总结 0417_图论-太平洋大西洋水流问题 0827_图论-最大人工岛 复习与总结 二刷做题速度提升了一大截&#xff0c;ヾ(◍∇◍)&#xff89;&#xff9e;加…

Linux重启网络后导致容器网络无法连接的解决办法

背景 有时候莫名奇妙的在一顿操作后&#xff0c;容器网络就坏了。然后外部无法访问容器的服务了。以前以为是操作了防火墙导致了容器无法被访问。但是最近经过仔细比较&#xff0c;防火墙规则并没有变化&#xff0c;但是容器就无法访问了。 分析 对于容器网络的讨论&#xff…

(六)PostgreSQL的组织结构(3)-默认角色和schema

PostgreSQL的组织结构(3)-默认角色和schema 基础信息 OS版本&#xff1a;Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本&#xff1a;16.2 pg软件目录&#xff1a;/home/pg16/soft pg数据目录&#xff1a;/home/pg16/data 端口&#xff1a;57771 默认角色 Post…

校园水电预付费系统

一、引言 校园水电预付费系统是一种现代化的管理方式&#xff0c;它改变了传统的后付费模式&#xff0c;实现了先付费后使用的理念&#xff0c;有效提高了校园资源的使用效率和管理效能。本文将从系统功能、操作流程、优点和实施策略四个方面详细介绍这一系统。 二、系统功能…

【五十六】【算法分析与设计】线段树之add+query操作,pair表示节点,自定义类型表示节点,真树结构实现线段树与数组实现线段树

线段树解决的问题 给你一个nums数组&#xff0c;1.L~R区间上的值全部加C。2.L~R区间上的值全部变成C。3.对L~R区间上求和操作。 对于第一个方法&#xff0c;如果正常遍历L~R加C&#xff0c;时间复杂度是O(N)。 对于第二个方法&#xff0c;如果正常遍历L~RC&#xff0c;时间复…

实时数据同步之Maxwell和Canal

文章目录 一、概述1、实时同步工具概述1.1 Maxwell 概述1.2 Canal概述 2、数据同步工作原理2.1 MySQL 主从复制过程2.2 两种工具工作原理 3、MySQL 的 binlog详解3.1 什么是 binlog3.2 binlog 的开启3.3 binlog 的分类设置 4、Maxwell和Canal对比5、环境安装 二、Maxwell 使用1…

upload-labs第十一十二关

第十一关 $is_upload false; $msg null; if(isset($_POST[submit])){$ext_arr array(jpg,png,gif);$file_ext substr($_FILES[upload_file][name],strrpos($_FILES[upload_file][name],".")1);if(in_array($file_ext,$ext_arr)){$temp_file $_FILES[upload_fil…

前端学习之DOM编程案例:点名案例和秒表案例

点名 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>点名案例</title><style>*{margin: 0;padding: 0;}</style> </head> <body><div id"container">…

软考135-上午题-【软件工程】-软件配置管理

备注&#xff1a; 该部分考题内容在教材中找不到。直接背题目 一、配置数据库 配置数据库可以分为以下三类&#xff1a; (1) 开发库 专供开发人员使用&#xff0c;其中的信息可能做频繁修改&#xff0c;对其控制相当宽松 (2) 受控库 在生存期某一阶段工作结束时发布的阶段产…

vue 实现实时搜索文档关键字并高亮显示

最近接到的一个新需求&#xff1a;实时搜索文档关键字并高亮显示&#xff0c;听起来好难的样子&#xff0c;仔细分析起来其实也蛮简单的。 实现思路 通过 input 实现关键字的输入&#xff0c;监听关键字的变化&#xff0c;用正则表达式来匹配关键字&#xff0c;然后给关键字添…

优思学院|什么叫三现主义?

三现主义是一种深入现场、直接观察和解决问题的管理方法&#xff0c;强调管理者必须亲身体验工作现场&#xff0c;从而更精准地理解和解决问题&#xff0c;提升管理和流程改进的效果。日本的丰田公司有一個日文術語為&#xff1a;Genchi Genbutsu&#xff08;英文&#xff1a;G…