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. java.lang.OutOfMemoryError GC overhead limit exceeded原因分析及解决方案

    最近一个上线运行良好的项目出现用户无法登录或者执行某个操作时,有卡顿现象.查看了日志,出现了大量的java.lang.OutOfMemoryError: GC overhead limit excee ...

  2. 【MySQL】MySQL 8.0.X的安装与卸载命令

    1.请读者自行下载MySQL Server https://dev.mysql.com/downloads/mysql/ 2.解压.zip文件 将mysql-8.0.12-winx64.zip解压到 ...

  3. python:枚举类型

    1.什么是枚举类型? 枚举类型可以看做是一系列常量的集合,通常用于表示某些有限且固定的集合,例如月份(一年有12个月).星期(一星期有七天).季节(一年四个季节)等. 2.枚举的定义 定义枚举首先要导 ...

  4. DB2中的MQT优化机制详解和实践

    MQT :物化查询表.是以一次查询的结果为基础  定义创建的表(实表),以量取胜(特别是在百万,千万级别的量,效果更显著),可以更快的查询到我们需要的结果.MQT有两种类型,一种是系统维护的MQT , ...

  5. Java线程学习详解

    线程基础 1. 线程的生命周期 1.1 新建状态: 使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态.它保持这个状态直到程序 start() 这个线程. 1 ...

  6. C++学习笔记5_智能指针

    1. 一般的指针int main(void){ int *p=new int; *p=20; delete p; return 0;}智能指针能自动回收#include<memory> 记 ...

  7. 学习笔记25_MVC前台API

    **当请求url的规则有所改变时,前台的所有超链接的href都得改,为了避免多处修改,可以href = "< %=url.Action("Controller",& ...

  8. 大公司喜欢问的Java集合类面试题

    Collection Collection是基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).一些Collection允许相同的元素而另一 ...

  9. 清华大学教学内核ucore学习系列(1) bootloader

    ucore是清华大学操作系统课程的实验内核,也是一个开源项目,是不可多得的非常好的操作系统学习资源 https://github.com/chyyuu/ucore_lab.git, 各位同学可以使用g ...

  10. EffectiveJava-4

    一.基本类型优先于装箱基本类型 Java的基本数据类型也叫做内置类型是java语言本身提供的数据类型,是引用其他类型的基础.Java的基本数据类型分为:整数类型.浮点类型.字符类型.布尔类型这四个类型 ...