1.最小生成树介绍

什么是最小生成树?

最小生成树(Minimum spanning tree,MST)是在一个给定的无向图G(V,E)中求一棵树T,使得这棵树拥有图G中的所有顶点,且所有边都是来自图G中的边,并且满足整棵树的边权值和最小。

2.prim算法

和Dijkstra算法很像!!请看如下Gif图,prim算法的核心思想是对图G(V,E)设置集合S,存放已被访问的顶点,然后每次从集合V-S中选择与集合S的最短距离最小的一个顶点(记为u),访问并加入集合S。之后,令顶点u为中间点,优化所有从u能到达的顶点v与集合s之间的最短距离。这样的操作执行n次,直到集合s中包含所有顶点。

不同的是,Dijkstra算法中的dist是从源点s到顶点w的最短路径;而prim算法中的dist是从集合S到顶点w的最短路径,以下是他们的伪码描述对比,关于Dijkstra算法的详细描述请参考文章

算法实现:

#include<iostream>
#include<vector>
#define INF 100000
#define MaxVertex 105
typedef int Vertex;
int G[MaxVertex][MaxVertex];
int parent[MaxVertex]; // 并查集
int dist[MaxVertex]; // 距离
int Nv; // 结点
int Ne; // 边
int sum; // 权重和
using namespace std;
vector<Vertex> MST; // 最小生成树 // 初始化图信息
void build(){
Vertex v1,v2;
int w;
cin>>Nv>>Ne;
for(int i=1;i<=Nv;i++){
for(int j=1;j<=Nv;j++)
G[i][j] = 0; // 初始化图
dist[i] = INF; // 初始化距离
parent[i] = -1; // 初始化并查集
}
// 初始化点
for(int i=0;i<Ne;i++){
cin>>v1>>v2>>w;
G[v1][v2] = w;
G[v2][v1] = w;
}
} // Prim算法前的初始化
void IniPrim(Vertex s){
dist[s] = 0;
MST.push_back(s);
for(Vertex i =1;i<=Nv;i++)
if(G[s][i]){
dist[i] = G[s][i];
parent[i] = s;
}
} // 查找未收录中dist最小的点
Vertex FindMin(){
int min = INF;
Vertex xb = -1;
for(Vertex i=1;i<=Nv;i++)
if(dist[i] && dist[i] < min){
min = dist[i];
xb = i;
}
return xb;
} void output(){
cout<<"被收录顺序:"<<endl;
for(Vertex i=1;i<=Nv;i++)
cout<<MST[i]<<" ";
cout<<"权重和为:"<<sum<<endl;
cout<<"该生成树为:"<<endl;
for(Vertex i=1;i<=Nv;i++)
cout<<parent[i]<<" ";
} void Prim(Vertex s){
IniPrim(s);
while(1){
Vertex v = FindMin();
if(v == -1)
break;
sum += dist[v];
dist[v] = 0;
MST.push_back(v);
for(Vertex w=1;w<=Nv;w++)
if(G[v][w] && dist[w])
if(G[v][w] < dist[w]){
dist[w] = G[v][w];
parent[w] = v;
}
}
} int main(){
build();
Prim(1);
output();
return 0;
}

关于prim算法的更加详细讲解请参考视频

3.kruskal算法

Kruskal算法也可以用来解决最小生成树的问题,其算法思想很容易理解,典型的边贪心,其算法思想为:

  • 在初始状态时隐去图中所有的边,这样图中每个顶点都是一个单独的连通块,一共有n个连通块
  • 对所有边按边权从小到大进行排序
  • 按边权从小到大测试所有边,如果当前测试边所连接的两个顶点不在同一个连通块中,则把这条测试边加入当前最小生成树中,否则,将边舍弃。
  • 重复执行上一步骤,直到最小生成树中的边数等于总顶点数减一 或者测试完所有边时结束;如果结束时,最小生成树的边数小于总顶点数减一,说明该图不连通。

请看下面的Gif图!

算法实现:

#include<iostream>
#include<string>
#include<vector>
#include<queue>
#define INF 100000
#define MaxVertex 105
typedef int Vertex;
int G[MaxVertex][MaxVertex];
int parent[MaxVertex]; // 并查集最小生成树
int Nv; // 结点
int Ne; // 边
int sum; // 权重和
using namespace std;
struct Node{
Vertex v1;
Vertex v2;
int weight; // 权重
// 重载运算符成最大堆
bool operator < (const Node &a) const
{
return weight>a.weight;
}
};
vector<Node> MST; // 最小生成树
priority_queue<Node> q; // 最小堆 // 初始化图信息
void build(){
Vertex v1,v2;
int w;
cin>>Nv>>Ne;
for(int i=1;i<=Nv;i++){
for(int j=1;j<=Nv;j++)
G[i][j] = 0; // 初始化图
parent[i] = -1;
}
// 初始化点
for(int i=0;i<Ne;i++){
cin>>v1>>v2>>w;
struct Node tmpE;
tmpE.v1 = v1;
tmpE.v2 = v2;
tmpE.weight = w;
q.push(tmpE);
}
} // 路径压缩查找
int Find(int x){
if(parent[x] < 0)
return x;
else
return parent[x] = Find(parent[x]);
} // 按秩归并
void Union(int x1,int x2){
if(parent[x1] < parent[x2]){
parent[x1] += parent[x2];
parent[x2] = x1;
}else{
parent[x2] += parent[x1];
parent[x1] = x2;
}
} void Kruskal(){
// 最小生成树的边不到 Nv-1 条且还有边
while(MST.size()!= Nv-1 && !q.empty()){
Node E = q.top(); // 从最小堆取出一条权重最小的边
q.pop(); // 出队这条边
if(Find(E.v1) != Find(E.v2)){ // 检测两条边是否在同一集合
sum += E.weight;
Union(E.v1,E.v2); // 并起来
MST.push_back(E);
}
} } void output(){
cout<<"被收录顺序:"<<endl;
for(Vertex i=0;i<Nv;i++)
cout<<MST[i].weight<<" ";
cout<<"权重和为:"<<sum<<endl;
for(Vertex i=1;i<=Nv;i++)
cout<<parent[i]<<" ";
cout<<endl;
} int main(){
build();
Kruskal();
output();
return 0;
}

关于kruskal算法更详细的讲解请参考视频

【algo&ds】8.最小生成树的更多相关文章

  1. 【algo&ds】4.B树、字典树、红黑树、跳表

    上一节内容[algo&ds]4.树和二叉树.完全二叉树.满二叉树.二叉查找树.平衡二叉树.堆.哈夫曼树.散列表 7.B树 B树的应用可以参考另外一篇文章 8.字典树Trie Trie 树,也叫 ...

  2. DS图--最小生成树

    题目描述 根据输入创建无向网.分别用Prim算法和Kruskal算法构建最小生成树.(假设:输入数据的最小生成树唯一.) 输入 顶点数n n个顶点 边数m m条边信息,格式为:顶点1 顶点2 权值 P ...

  3. 【algo&ds】2.线性表

    1.线性表 线性表(英语:Linear List)是由n(n≥0)个数据元素(结点)a[0],a[1],a[2]-,a[n-1]组成的有限序列. 其中: 数据元素的个数n定义为表的长度 = " ...

  4. 【algo&ds】【吐血整理】4.树和二叉树、完全二叉树、满二叉树、二叉查找树、平衡二叉树、堆、哈夫曼树、B树、字典树、红黑树、跳表、散列表

    本博客内容耗时4天整理,如果需要转载,请注明出处,谢谢. 1.树 1.1树的定义 在计算机科学中,树(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结 ...

  5. 【algo&ds】3.栈和队列

    1.堆栈 堆栈(Stack):具有一定操作约束的线性表(只在一端(栈顶,Top)做插入.删除) 先进后出特性 1.1堆栈的抽象数据类型描述 类型名称: 堆栈(Stack) 数据对象集:一个有0个或多个 ...

  6. 【algo&ds】1.时间复杂度和空间复杂度分析

    1.时间复杂度分析O(f(n)) 分析方法 只关注循环执行次数最多的一段代码 加法原则 乘法原则 高优先级原则 常见时间复杂度量级 多项式量级和非多项式量级.其中,非多项式量级只有两个:O(2^n) ...

  7. 【algo&ds】0.数据结构和算法入门

    解决问题方法的效率,跟数据的组织方式有关 解决问题方法的效率,跟空间的利用效率有关 解决问题方法的效率,跟算法的巧妙程度有关 什么是数据结构 数据对象在计算机中的组织方式 逻辑结构 物理存储结构 数据 ...

  8. 【algo&ds】7.最短路径问题

    单源最短路径问题:从某固定源点出发,求其到所有其他顶点的最短路径 (有向)无权图:BFS (有向)有权图:Dijkstra算法 多源最短路径问题:求任意两顶点间的最短路径 直接将单源最短路算法调用|V ...

  9. 【algo&ds】9.拓扑排序、AOV&AOE、关键路径问题

    对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性 ...

随机推荐

  1. 《如何学习基于ARM嵌入式系统》笔记整理

    author:Peong time:20190603 如何学习基于ARM嵌入式系统 一.嵌入式系统的概念 从硬件上讲,将外围器件,与CPU集成在一起. 从操作系统上讲,定制符合要求的系统内核 从应用上 ...

  2. git jenkins 部署java项目

    1.Java项目部署基本概述:  1.什么是Java项目?  2.为什么Java项目需要使用Maven编译?  3.手动实现Java项目构建?  4.手动实现Java项目架构图? 源码包   jar包 ...

  3. 网络攻防实验任务三_(2)X-Scan通用漏洞扫描实验

    首先在宿主机中打开xscan_gui.exe,结果系统直接将它删掉了. 大概是因为开了防火墙的缘故. 于是我在win7虚拟机中运行这个程序. 并且关闭防火墙,在win7中可以运行 我再试了一下win1 ...

  4. solr学习篇(一) solr7.4 安装配置篇

    目录: solr简介 solr安装 创建core 1.solr简介 solr是企业级应用的全文检索项目,它是基于Apache Lucence搜索引擎开发出来的用于搜索的应用工程 运行环境:solr需要 ...

  5. Spring Cloud - Eureka /actuator/info 如何显示信息

    在pom.xml中添加 <!-- actuator监控信息完善 --> <dependency> <groupId>org.springframework.boot ...

  6. PHP Windows下使用Memcached扩展

    github上发现了一个很好用的小文件,能够 模拟出php_memcached.dll的PHP memcached扩展. PHP memcached client 已知PCEL有两个memcache ...

  7. os模块/sys模块/json/pickle模块/logging模块(day16整理)

    目录 今日内容 os模块 对文件操作 对文件夹此操作 辅助性的 了解 sys模块 json和pickle模块 json模块 pickle模块 logging模块 日志级别 添加设置 自定义配置 今日内 ...

  8. 设计模式(十)Strategy模式

    Strategy模式,就是用来整体地替换算法,可以轻松地以不同的算法解决同一个问题. 还是根据一个示例程序来理解这种设计模式吧.先看一下示例程序的类图. 然后看示例程序代码. package bigj ...

  9. unity5.6.1 videoPlayer

    unity5.6开始增加了videoPlayer,使得视频播放相对比较简单,项目需求进行了一下研究应用,也遇到很多坑,Google 百度一下发现确实有这些问题,一些简单问题如下: 1)播放无声音 2) ...

  10. 中文预训练模型ERNIE2.0模型下载及安装

    2019年7月,百度ERNIE再升级,发布持续学习的语义理解框架ERNIE 2.0,及基于此框架的ERNIE 2.0预训练模型, 它利用百度海量数据和飞桨(PaddlePaddle)多机多卡高效训练优 ...