C++ Prim和kruskal求最小生成树算法

news/2024/7/15 17:28:10 标签: 算法, c++, 图论

C++ Prim和 kruskal 求最小生成树算法

生成树:在图中找一棵包含图中的所有节点的树,生成树是含有图中所有顶点的无环连通子图。所有可能的生成树中,权重和最小的那棵生成树就叫最小生成树。在无向加权图中计算最小生成树,使用最小生成树算法的现实场景中,图的边权重一般代表成本、距离这样的标量。

kruskal

这里就用到了贪心思路:将所有边按照权重从小到大排序,从权重最小的边开始遍历,如果这条边和mst中的其它边不会形成环,则这条边是最小生成树的一部分,将它加入mst集合;否则,这条边不是最小生成树的一部分,不要把它加入mst集合。

#include <iostream>
#include <algorithm>
using namespace std;

class UF {
  private:
  	//连通分量的个数
  	int count;
  	//数组:每一个节点对应一个集合(树)
  	int parent[100];
 public:
  	//构造函数
  	UF(int n) {
   		this->count=n;//0  9
   		for(int i=0; i<n; i++) {
    		this->parent[i]=i;
   		}
  	}
  /*
  * 合并函数,构建边
  */
  void union_(int a,int b) {
   //检查a 和 b 是不是同一个集合
   //查找彼此的根节点
   int aroot= this->findRoot(a);
   int broot=this->findRoot(b);
   //如果是 什么都不做
   if(aroot==broot)return ;
   //如果不是,合并
   //  this->parent[broot]=aroot;
   this->parent[aroot]=broot;
   this->count--;
  }
  /*
  * 查找某一个节点的父节点
  */
  int findRoot(int id) {
   //根节点特点,parent[id]==id
   while( this->parent[id]!=id ) {
    id= this->parent[id];
   }
   return id;
  }
  /*
  *检查连通性
  */
  bool isConnection(int a,int b) {
   int aroot= this->findRoot(a);
   int broot=this->findRoot(b);
   return aroot==broot;
  }
};

struct Edge {
 int f;
 int t;
 int w;
//重写
 bool operator<( const Edge & edge  )  const {
  return this->w< edge.w;
 }
};

int main() {
 int n=3,m=3; // 
 int weight=0;
 cin>>n>>m;
 UF uf(n+1); //  
 Edge edges[100];
 int f,t,w;
 for(int i=0; i<m; i++) {
  cin>>f>>t>>w;
  edges[i]= {f,t,w};
 }
 //排序
 sort( edges,edges+m);
 for(int i=0; i<m; i++) {
  	if( uf.isConnection( edges[i].f,edges[i].t  ) ==true  ) {
   		continue;
  	}
  	weight+=edges[i].w;
  	uf.union_(edges[i].f,edges[i].t );
 }
 cout<< weight;
 return 0;
}

Prim

在图中进行广度搜索,使用优先队列存储边信息。

#include <bits/stdc++.h>

using namespace std;
/*
* 顶点类型
*/
struct Ver {
 //顶点编号
 int vid=0;
 //第一个邻接点
 int head=0;
 //是否被选择
 int isSel=0;
};

/*
* 边
*/
struct Edge {
 //邻接点
 int to;
 //下一个
 int next=0;
 //权重
 int weight;
 //是否已经添加
 bool isVis=0;
 //重载函数
 bool operator<( const Edge & edge ) const {
  return this->weight > edge.weight;
 }
};

class Prim {
 private:
  //存储所有顶点
  Ver vers[100];
  //存储所有边
  Edge edges[100];
  //顶点数,边数
  int v,e;
  //优先队列
  priority_queue<Edge> proQue;
  //最小生成树的权重
  int weight=0;

 public:
  Prim( int v,int e ) {
       this->v=v;
       this->e=e;
       init();
  }
  void init() {
      
   for(int i=1; i<=v; i++) {
    //重置顶点信息
    vers[i].vid=i;
    vers[i].head=0;
    vers[i].isSel=0;
   }

   int f,t,w;
   for(int i=1; i<=e; i++) {
        cin>>f>>t>>w;
        //设置边的信息
        edges[i].to=t;
        edges[i].weight=w;
        //头部插入
        edges[i].next=vers[f].head;
        vers[f].head=i;
   }
  }

  void pushQue(Ver & ver) {

       for( int i=ver.head; i!=0; i=edges[i].next) {
        int to=edges[i].to;
        if(  edges[i].isVis==false ) {
         edges[i].isVis=true;
         //入队列
         proQue.push( edges[i] );
        }
       }
  }

  void prim(int start) {


   //初始化优先队列
   vers[start].isSel=true;
   pushQue(vers[start]);

   while( !proQue.empty() ) {
    //出队列
    Edge edge=proQue.top();
    proQue.pop();

    if(  vers[edge.to].isSel  ==true)continue;
    vers[edge.to].isSel  =true;

    weight+=edge.weight;
    //邻接边入栈
    pushQue( vers[edge.to] );
   }

   for(int i=1; i<=v; i++) {
    if( vers[i].isSel )cout<<i<<"\t";
   }
   cout<<weight<<endl;

  }

};

int main() {
 int v,e;
 cin>>v>>e;
 Prim prim(v,e);
 prim.prim(1);
 return 0;
}

http://www.niftyadmin.cn/n/5161583.html

相关文章

717. 简单斐波那契

题目 思路 很简单&#xff0c;递推&#xff0c;当前这项等于前两项的和&#xff0c;那就先初始化第一项和第二项即可。 代码 #include<bits/stdc.h> using namespace std; const int N 1e5 3; int a[N]; int main() {int n; cin >> n;a[0] 0;a[1] 1;for (in…

小而美的服务端推送技术SSE之理论与实战(含demo)

[[toc]] SSE 是什么? 基本特点 SSE: Server-Sent Events用途: 服务器向浏览器推送信息, 注意反过来不行本质: 基于http协议的服务端推送技术特点: 响应头mimetype 为 text/event-stream, keep connection open数据: 流信息(streaming),数据流不是一次性数据包,会连续不…

卓越进行时 | 聚焦网络安全学科建设 深化校企合作协同育人

近日&#xff0c;由南京赛宁信息技术有限公司&#xff08;赛宁网安&#xff09;主办的“网络空间安全学科发展及产业学院平台运营模式专题研讨活动”在南京市未来科技城网络安全卓越中心举行&#xff0c;来自成都信息工程大学和四川省网络空间安全协会的多名专家学者齐聚江宁&a…

算法题:平均数为k的最长连续子数组

问题描述 1.题目描述 给定 n个正整数组成的数组&#xff0c;求平均数正好等于 k 的最长连续子数组的长度。 2.I/O描述 输入描述&#xff1a; 第一行输入两个正整数n和k&#xff0c;用空格隔开。 第二行输入n个正整数a_i&#xff0c;用来表示数组。 输出描述&#xff1a; 如…

Banana Pi BPI-M6(Raspberry Pi 5 替代品)初始设置及固件烧录

Banana Pi BPI-M6&#xff1a;初始设置和镜像烧录 Banana Pi BPI-M6 的首次测试 在上一篇文章中&#xff0c;我比较了Banana Pi BPI-M6和Raspberry Pi 5的硬件特性。两者都拥有出色的硬件技术&#xff0c;在性能方面应该不会有太大的问题。 今天我想测试一下 Banana Pi。作为…

Python Selenium 执行 JavaScript

简介 Selenium是一个用于自动化浏览器操作的工具&#xff0c;可以模拟人工操作&#xff0c;执行各种浏览器操作&#xff0c;包括点击、输入文字、提交表单等。而JavaScript是一种常用的脚本语言&#xff0c;用于在网页上添加交互性和动态性。在Python中使用Selenium执行JavaSc…

linux粘滞位的介绍及使用

文章目录 1.粘滞位的引入2.粘滞位的使用 1.粘滞位的引入 首先看一个场景 已知 对目录无w权限时 无法进行目录中的文件的创建/删除操作但是普通用户通过sudo命令 以root身份创建一个文件 rw- r-- r-- 普通用户此时是other 没有w权限 但却可以删除 [root和普通用户在一个目录下时…

【C++】:内存管理:C++内存分布 || C++中动态内存管理(new || delete)

&#x1f4ed;1. C/C内存分布 【说明】 &#x1f0cf;1. 栈又叫堆栈–非静态局部变量/函数参数/返回值等等&#xff0c;栈是向下增长的 &#x1f0cf;2. 内存映射段是高效的I/O映射方式&#xff0c;用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存&#xff…