【算法】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算法 或许在生活中,经常会碰到针对某一个问题,在众多的限制条件下,如何去寻找一个最优解?可能大家想到了很多诸如“线性规划”,“动态规划” 这些经典 ...
随机推荐
- [C#学习笔记之异步编程模式2]BeginInvoke和EndInvoke方法 (转载)
为什么要进行异步回调?众所周知,普通方法运行,是单线程的,如果中途有大型操作(如:读取大文件,大批量操作数据库,网络传输等),都会导致方法阻塞,表现在界面上就是,程序卡或者死掉,界面元素不动了,不响应 ...
- CorelDRAW升级计划--如何购买
了解通过全新 CorelDRAW 2017升级计划更新此图形设计软件所有最新功能的实惠方案.助升级计划,您可以在下一主要产品版本推出时便收到该版本,从而始终使您的产品保持最新.升级计划取代为 X6 和 ...
- Java数据库开发
Nosql数据库使用场景 首先需要确认一个问题,nosql能做什么?在现在的开发领域中nosql可以实现文档存储(BSON.JSON).缓存存储.图像缓存(图像搜索),但是对于nosql的具体应用场景 ...
- 使用其他Java工程导入hadoop源码用于在hadoop工程中查看源码
疑问:在开发hadoop程序的时候,有时候需要查看hadoop的源码,但是开发环境看不到,甚是烦恼,经过网上搜索和琢磨,终于实现了,虽然有点绕,但是目的达到了. 第一步:下载hadoop的源码包:ha ...
- BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)
题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个 ...
- 安装SSH、配置SSH无密码登录 ssh localhost
集群.单节点模式都需要用到 SSH 登陆(类似于远程登陆,你可以登录某台 Linux 主机,并且在上面运行命令),Ubuntu 默认已安装了 SSH client,此外还需要安装 SSH server ...
- 为什么要清除BSS段
如题,看到uboot里有清除BSS段的代码,想知道这样做的目的是什么啊,BSS段默认值本来就是0了啊,希望大哥大姐们能详细的解说下,谢谢了 bss 段描述了未初始化的全局变量和静态变量的大小等信息,但 ...
- Postgresql数据库的一些字符串操作函数
今天做项目遇到客户反映了一个麻烦的事情,有一些数据存在,但就是在程序中搜索不出来,后来分析,发现问题为数据前面有几个空白字符,后来用SQL查询了一下,发现八九个数据表中,数千万条数据中有将近三百万条数 ...
- jenkins 安装遇到的坑
最后启用安全的时候遇到一点坑,直接写了一个用户上去,没有勾选权限,然后在登录就说没有 overright/等,然后需要修改配置文件conf.xml 在主目录下. ...
- COJS 1752. [BOI2007]摩基亚Mokia
1752. [BOI2007]摩基亚Mokia ★★★ 输入文件:mokia.in 输出文件:mokia.out 简单对比时间限制:5 s 内存限制:128 MB [题目描述] 摩尔瓦 ...