【算法】prim算法(最小生成树)(与Dijkstra算法的比较)
最小生成树:
生成树的定义:给定一个无向图,如果它的某个子图中任意两个顶点都互相连通并且是一棵树,那么这棵树就叫做生成树。(Spanning Tree)
最小生成树的定义:在生成树的基础上,如果边上有权值,那么使得边权和最小的生成树叫做最小生成树。(Minimum Spanning Tree )
解决生成树有两种常用的算法:Kruskal算法和prim算法。
这里我们讲的是prim算法求生成树的解法。
算法思想:
ans = 0;(表示权值和)
1.在无向图的基础上,想象我们有一个点的集合X(初始状态为空)。
2.在集合X中加入一个初始点x,用这个初始点更新其他点离集合X的距离mincost[ ],标记初始点为使用过(使用过:加入集合X)。
3.找一个未使用过(集合X外的点)的离集合X最小距离最小的点,找到了这样一个点,将这个点加入集合X,ans += 这个与集合X的距离,
用这个新加入的点更新其他点离集合X的最小距离mincost[ ],标记新加入的点为使用过,继续执行第3步;找不到这样一个点,则进入第4步。
4.输出ans。
mincost[i] 表示点i离集合X的最小距离。(离集合X中所有点中最近的点的距离)
简单来说就是:
想象一下,有10张面额不同的毛爷爷在你面前,每次只能拿1张,只能拿5次,你肯定会每次都拿这n张(n<=10)中最大的那张,
这样拿5次,让总额最大。这个算法也是同样的道理,不断的加入可触及的最近的点,最后权值一定是最小的。
额,当然10张不同的毛爷爷是不存在的。所以一分都拿不到,还是看代码吧:
代码:
#include <bits\stdc++.h>
using namespace std;
#define INF 2147483647
#define MAX_V 1000
#define MAX_E 2000 int cost[MAX_V][MAX_V]; // cost[i][j] 表示顶点i到顶点j的权值,不存在时为INF
int mincost[MAX_V]; // mincost[i] 表示i点与集合X的最小距离
bool used[MAX_V]; // used[i]表示点i是否在集合中
int V; //顶点数 //表示从点x产生的最小生成树,这么考虑是因为整个图可能不连通
int prim(int x){
//最初X集合为空,每个点到集合X的最小距离都是INF
for(int i = ;i < V; ++i){
mincost[i] = INF;
used[i] = false;
} //将点x与集合X的距离置为0,第一次集合X会加入点x
mincost[x] = ; int res = ; while(true){
int v = -;
//找到离集合X最近的点,第一次加入点x
for(int u = ;u < V; ++u){
if(!used[u] && (v == - || mincost[u] < mincost[v])) v = u;
}
//如果所有点可达的点都加入集合X中了,就跳出
if(v == -) break;
used[v] = true;
res += mincost[v]; mincost[v] = ; //把点v加入到集合X中,这一步帮助理解,可写可不写 ,因为cost[v][v] = 0 //用新加入的点v更新其他点离与集合X的最小距离
for(int u = ;u < V; ++u){
mincost[u] = min(mincost[u] , cost[v][u]);
}
}
return res;
} int main(){
}
与Dijkstra算法的比较
Prim算法与Dijkstra算法都是从某个点出发,不断加入最近的点。最终都要把所有可以加的点加完。
Prim算法是求最小生成树,Dijkstra是求单源最短路径。
来个Dijkstra求单源最短路径的代码,与Prim算法比较一下:
#include <bits\stdc++.h>
using namespace std;
#define INF 2147483647
#define MAX_V 1000
#define MAX_E 2000 //单源最短路径问题(Dijkstra算法) int cost[MAX_V][MAX_V]; //cost[u][v]表示e = (u,v)的权值
int d[MAX_V]; //顶点s出发的最短距离 //不同处1
bool used[MAX_V]; //标记使用过的点
int V; //顶点数 void dijkstra(int s){
fill(d, d+V, INF);
fill(used, used + V, INF);
d[s] = ; while(true){
int v = -; //找到一个距离最近的没有使用过的点
for(int u = ;u < V; u++){
if(!used[u] && (v == - || d[u] < d[v])) v = u;
}
//如果所有的点都被使用过了,则break
if(v == -) break; //标记当前点被使用过了
used[v] = true; //更新这个找到的距离最小的点所连的点的距离
for(int u = ;u < V; u++){
d[u] = min(d[u], d[v] + cost[v][u]); //不同处2
} }
} int main(){
}
我们可以看到代码基本上是一样的,只有
不同处1:Djikstra中用d[i]表示i点离源点的最短距离,Prim中用mincost[i] 表示i点与集合X的距离。
不同处2:Djikstra中更新d[u] = min( d[u] , d[v] + cost[v][u] ); 用新加入的点更新其他点与源点的最小距离。
Prim中更新mincost[u] = min( mincost[u] , cost[v][u] ); 用新加入的点更新点i与集合X的最小距离。
我认为只用加几行代码,无论是在prim中加,还是在Dijkstra中加,就既可以求单源最短路径,又可以求最小生成树了。
【算法】prim算法(最小生成树)(与Dijkstra算法的比较)的更多相关文章
- Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例
本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法).分享给大家供大家参考,具体如下: # coding:utf-8 # Dijkstra算法--通过边实现松弛 # 指定一个 ...
- python数据结构与算法——图的最短路径(Dijkstra算法)
# Dijkstra算法——通过边实现松弛 # 指定一个点到其他各顶点的路径——单源最短路径 # 初始化图参数 G = {1:{1:0, 2:1, 3:12}, 2:{2:0, 3:9, 4:3}, ...
- 图论算法》关于SPFA和Dijkstra算法的两三事
本来我是想把这两个算法分开写描述的,但是SPFA其实就是Dijkstra的稀疏图优化,所以其实代码差不多,所以就放在一起写了. 因为SPFA是Dijkstra的优化,所以我想来讲讲Dijkstra. ...
- [C++]多源最短路径(带权有向图):【Floyd算法(动态规划法)】 VS n*Dijkstra算法(贪心算法)
1 Floyd算法 1.1 解决问题/提出背景 多源最短路径(带权有向图中,求每一对顶点之间的最短路径) 方案一:弗洛伊德(Floyd算法)算法 算法思想:动态规划法 时间复杂度:O(n^3) 形式上 ...
- 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)
一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...
- 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(一)
一.算法介绍 迪杰斯特拉算法(英语:Dijkstra's algorithm)由荷兰计算机科学家艾兹赫尔·迪杰斯特拉在1956年提出.迪杰斯特拉算法使用了广度优先搜索解决赋权有向图的单源最短路径问题. ...
- 贪心算法(Greedy Algorithm)最小生成树 克鲁斯卡尔算法(Kruskal's algorithm)
克鲁斯卡尔算法(Kruskal's algorithm)它既是古典最低的一个简单的了解生成树算法. 这充分反映了这一点贪心算法的精髓.该方法可以通常的图被表示.图选择这里借用Wikipedia在.非常 ...
- Dijkstra算法(二)之 C++详解
本章是迪杰斯特拉算法的C++实现. 目录 1. 迪杰斯特拉算法介绍 2. 迪杰斯特拉算法图解 3. 迪杰斯特拉算法的代码说明 4. 迪杰斯特拉算法的源码 转载请注明出处:http://www.cnbl ...
- 经典算法题每日演练——第十七题 Dijkstra算法
原文:经典算法题每日演练--第十七题 Dijkstra算法 或许在生活中,经常会碰到针对某一个问题,在众多的限制条件下,如何去寻找一个最优解?可能大家想到了很多诸如“线性规划”,“动态规划” 这些经典 ...
随机推荐
- TCP和UDP的具体区别
TCP和UDP的最完整的区别 TCP UDP TCP与UDP基本区别: 1.基于连接与无连接 2.TCP要求系统资源较多,UDP较少: 3.UDP程序结构较简单 4.流模式(TCP)与数据报模式(UD ...
- SQLSERVER 链接服务器
1. 执行代码 EXEC sp_addlinkedserver @server='XLZFSqlServer', --链接服务器别名 @srvproduct='', @provider='SQLOLE ...
- Sumblime Text3中使用vue-cli创建vue项目,代码不高亮,解决
问题如下:在Sumblime Text3中打开vue-cli常见的项目,代码一片灰色 解决如下: 第一步:下载文件Vue components 链接 GitHub - vuejs/vue-synta ...
- windows及git常用命令
windows常用命令: 创建文件夹:md 文件夹名 创建空的文件:type nul>文件名 创建有内容文件:echo "内容">文件名 查看文件内容:type +文件 ...
- js判断传入时间和当前时间大小
//判断时间是否过期 function judgeTime(time){ var strtime = time.replace("/-/g", "/");//时 ...
- (转载)Android项目实战(二十七):数据交互(信息编辑)填写总结
Android项目实战(二十七):数据交互(信息编辑)填写总结 前言: 项目中必定用到的数据填写需求.比如修改用户名的文字编辑对话框,修改生日的日期选择对话框等等.现总结一下,方便以后使用. 注: ...
- 页面定制CSS代码初探(三):设置正文最小高度
前言 没想到再次写这篇,已经过去1年半了. 现在审美也发生了改变,一开始做的样式全删了,只保留了h2的样式.原先认为界面要宽,两边留太多空很浪费,看惯了知乎和简书,觉得默认最大1000px的排版也不错 ...
- ZBrush中Tool工具的保存
ZBrush软件的界面及操作方法与其他的三维软件完全不同,很多初学者常常会觉得有些困难,接下来我们就讲解一下ZBrush®最为基础的操作-Tool工具的保存. 首先要明白什么是Tool工具?我们创建的 ...
- Eclipse本地创建新的GIT分支,并推送至远程Git分支
本地创建新的GIT分支: 1.右击要创建新分支的项目——Team——Switch To——New Branch…: 2.在弹出的对话框中name框中输入要创建的分支名称,(如果是当前显示的要拷贝的分支 ...
- 51nod 1302(贪心+平衡树)
能推出一些性质. 矩形肯定是全部躺着或全部立着比较优. 如图x1显然等于x2,y1显然小于y2. 所以我们就让它们都躺下吧. 然后一定有一组的宽为宽最小的矩形的宽. 然后我们枚举另一组的宽最小的矩形. ...