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

news2024/11/20 6:36:55

最小生成树算法的实现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;

}


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

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

相关文章

施耐德 PLC 及模块 ModbusTCP 通信配置方法

1. 通过【I/O扫描器】服务进行读写 相关文档&#xff1a;各模块说明书仅 NOE 网卡模块、部分 CPU 自带的网口支持 优点&#xff1a;不需要额外编程&#xff0c;系统自动周期型读写数据缺点&#xff1a;扫描周期不定&#xff0c;程序无法控制数据刷新的时序 2. 通过内部程序…

C语言---贪吃蛇(一)---准备工作

文章目录 前言1.Win32 API介绍1.1.Win32 API1.2. 控制台程序1.3.控制台屏幕上的坐标[COORD](https://learn.microsoft.com/zh-cn/windows/console/coord-str)1.4.[GetStdHandle](https://learn.microsoft.com/zh-cn/windows/console/getstdhandle)1.5.[GetConsoleCursorInfo](h…

Navicat 干货 | 了解 PostgreSQL 规则

PostgreSQL 是一个强大的开源关系型数据库管理系统&#xff0c;为增强数据管理和操作提供了丰富的功能。这些功能中包含了规则&#xff0c;这是一种用于控制数据库内部查询和命令处理方式的机制。本文将探讨 PostgreSQL 规则的工作原理&#xff0c;以及它们与触发器的区别&…

替代普通塑料吸头的PFA移液吸头

目前市场上的规格&#xff1a;0.01ml、0.05ml、0.1ml、0.2ml、0.5ml、1ml、2ml、5ml、10ml等均可定制加工PFA材质枪头&#xff0c;可以适配市场上大部分移液枪&#xff0c;普兰德&#xff0c;大龙&#xff0c;赛默飞&#xff0c;赛多利斯&#xff0c;力辰、吉尔森&#xff0c;瑞…

Flask中的JWT认证构建安全的用户身份验证系统

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Flask中的JWT认证&#xff1a;构建安全的用户身份验证系统 随着Web应用程序的发展&#xf…

粤嵌—2024/4/19—三数之和

代码实现&#xff1a; 方法一&#xff1a;排序 回溯——超时 有错误 /*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returned array and *columnSizes array must be malloced, assu…

Scanpy(2)多种可视化

本篇内容为scanpy的可视化方法&#xff0c;可以分为三部分&#xff1a; embedding的散点图&#xff1b;用已知marker genes的聚类识别&#xff08;Identification of clusters&#xff09;&#xff1b;可视化基因的差异表达&#xff1b; 我们使用10x的PBMC数据集&#xff08;…

「泰雷兹」新合作推进南美太空安全,量子加密守护卫星系统

在第23届国际航空航天博览会&#xff08;FIDAE&#xff09;期间&#xff0c;泰雷兹与SeQure Quantum签署了一份谅解备忘录&#xff0c;SeQure Quantum是一家专门从事加密和密码学量子技术的智利公司。二者联手探索和制定与智利太空项目相关的联合战略、技术和知识转让。 在一个…

docker安装并跑通QQ机器人实践(2)-签名服务器bs-qsign搭建

在前文中&#xff0c;我们详尽阐述了QQ机器人的搭建过程及其最终实现的各项功能展示。接下来&#xff0c;我们将转向探讨该项目基于Docker构建服务的具体实践。本篇将以QQ机器人签名服务——qsign为起点&#xff0c;逐步展开论述。 1 获取和运行 xzhouqd/qsign:8.9.63 镜像 1.…

Java开发从入门到精通(二十):Java的面向对象编程OOP:IO流文件操作的读取和写入

Java大数据开发和安全开发 &#xff08;一&#xff09;Java的IO流文件读写1.1 IO流前置知识1.1.1 ASCII字符集1.1.2 GBK字符集1.1.3 Unicode字符集1.1.4 UTF-8字符集1.1.4 Java的编码解码 1.2 IO流的基础知识1.2.1 认识I0流1.2.2 应用场景1.2.3 如何学I0流1.2.3.1 先搞清楚I0流…

移除离群点------PCL

statisticalOutlierRemoval滤波器移除离群点 /// <summary> /// 使用statisticalOutlierRemoval滤波器移除离群点 /// </summary> /// <param name"cloud">被过滤的点云</param> /// <param name"meank"></param> //…

lementui el-menu侧边栏占满高度且不超出视口

做了几次老是忘记&#xff0c;这次整理好逻辑做个笔记方便重复利用&#xff1b; 问题&#xff1a;elementui的侧边栏是占不满高度的&#xff1b;但是使用100vh又会超出视口高度不美观&#xff1b; 解决办法&#xff1a; 1.获取到侧边栏底部到视口顶部的距离 2.获取到视口的高…

实验室三大常用仪器1---示波器的基本使用方法(笔记)

目录 示波器的作用 示波器的基础操作方法 示波器测量突变脉冲 示波器的作用 示波器能帮助我们干什么&#xff1f; 比如说某个电源用万用表测量是稳定的5V输出 但是用示波器一看确实波涛汹涌 这样的电源很可能回导致系统异常工作 又比如电脑和单片机进行串口通信时&#xf…

c 多文件编程

1.结构目录 声明类:用于声明方法,方便方法管理和调用&#xff1b; 实现类:用于实现声明的方法; 应用层:调用方法使用 写过java代码的兄弟们可以这么理解&#xff1a; 声明类 为service层 实现类 为serviceimpl层 应用层 为conlloter层 2.Dome 把函数声明放在头文件xxx.h中&…

什么是 GitHub Wiki 以及如何使用它?

GitHub Wiki 是你项目文档的一个很好的地方。你可以使用 wiki 来创建、管理和托管你的存储库的文档&#xff0c;以便其他人可以使用并为你的项目做出贡献。 GitHub Wiki 很容易开始使用&#xff0c;无需安装任何其他软件。最好的部分是 wiki 与你的 GitHub 存储库集成在一起。…

汇编语言——输入4位以内的16进制数,存进BX

data segment data ends stack segment stackdw 100 dup (?)top label word stack ends code segmentassume cs:code,ds:data,ss:stack main proc farmov ax,datamov ds,axmov ax,stackmov ss,axlea sp,topmov bx,0mov cx,4 ;最多输入4位16进制数 L1: mov ah,7 ;用7号功能…

进程互斥的实现

目录 一. 进程同步二. 进程互斥三. 进程互斥软件实现四. 进程互斥硬件实现4.1 中断屏蔽方法4.2 test and set 指令4.3 Swap 指令 五. 互斥锁六. 信号量机制6.1 整型信号量6.2 记录型信号量6.3 信号量机制实现进程互斥6.4 信号量机制实现进程同步6.5 信号量机制实现进程前驱关系…

物流单打印模板怎么设置,物流发货单打印软件操作教程

物流单打印模板怎么设置&#xff0c;物流发货单打印软件操作教程 一、前言 以下软件操作教程以&#xff0c;佳易王物流货运单管理系统软件为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 佳易王物流单管理系统软件直接在空白单上打印可以在卷纸…

2024年短剧视频如何下载

下载工具 2024年是短剧继续增长的年代 本文以短剧小程序为例子&#xff0c;工具(下载高手)我已经打包好了 1.首先解压我给大家准备的压缩包 2.把微信程序退出&#xff0c;一定要是电脑右下角右键然后退出微信&#xff0c;直接关掉微信不算退出 3.然后打开下载高手,第一次运行…

Java作业6-Java类的基本概念三

编程1 import java.util.*;abstract class Rodent//抽象类 {public abstract String findFood();//抽象方法public abstract String chewFood(); } class Mouse extends Rodent {public String findFood(){ return "大米"; }public String chewFood(){ return "…