图的最短路径——dijkstra算法和Floyd算法
dijkstra算法
求某一顶点到其它各个顶点的最短路径;已知某一顶点v0,求它顶点到其它顶点的最短路径,该算法按照最短路径递增的顺序产生一点到其余各顶点的所有最短路径。
对于图G={V,{E}};将图中的顶点分为两组:
第一组S:求出已知顶点的最短路径的集合
第二组V-S:尚未求出最短路径的顶点集合(开始为V-{v0}的全部顶点)
该算法将最短路径以递增顺序逐个将第二组顶点加入到第一组顶点中,直到所有的顶点都被加入到第一组顶点集S为止。
dijkstra算法和最小生树中的prim算法类似,都是把顶点看做集合,向所求集合中加点
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; const int INF=0x3f3f;
class Graph
{
private:
int num;
int e;
vector<vector<int> > arr;//存储图的邻接矩阵
vector<bool> visit;//标记该结点是否用过
vector<int> path;//从v0到其他结点的最短路径
public:
Graph();
void dijkstra(const int &i);
};
Graph::Graph()
{
cout<<" num"<<endl;
cin>>num;
cout<<" e"<<endl;
cin>>e; visit.resize(num,false);
path.resize(num); arr.resize(num);
for(int i=;i<num;++i)
arr.at(i).resize(num,INF); cout<<" 边的起始点和终点&&权值"<<endl;
pair<int,int> p;
for(int i=;i<e;++i)
{
cin>>p.first>>p.second;
cin>>arr.at(p.first-).at(p.second-);
}
}
void Graph::dijkstra(const int &index)
{
//首先存储的是index结点到其他节点的最短路径的值
for(int i=;i<num;++i)
path.at(i)=arr.at(index-).at(i);
//初始化visit
visit.at(index-)=true; for(int check=;check<num-;++check)
{
int Min=INF,flag=;
for(int i=;i<num;++i)
{
if(!visit.at(i)&&path.at(i)<Min)
{
flag=i;
Min=path.at(i);
}
}
visit.at(flag)=true;
for(int i=;i<num;++i)//如果由于v0结点的加入导致index结点到其它接点的值变小更新path
{
if(path.at(i)>path.at(flag)+arr.at(flag).at(i))
path.at(i)=path.at(flag)+arr.at(flag).at(i);
}
}
for(int i=;i<num;++i)
cout<<path.at(i)<<"\t";
cout<<endl;
}
int main()
{
Graph g;
g.dijkstra();
return ;
}
floyd算法
如果要让任意两点(例如从顶点a点到顶点b)之间的路程变短,只能引入第三个点(顶点k),并通过这个顶点k中转即a->k->b,才可能缩短原来从顶点a点到顶点b的路程。那么这个中转的顶点k是1~n中的哪个点呢?甚至有时候不只通过一个点,而是经过两个点或者更多点中转会更短。
当任意两点之间不允许经过第三个点时,这些城市之间最短路程就是初始路程

一:假如现在只允许经过1号顶点,求任意两点之间的最短路程,只需判断e[i][1]+e[1][j]是否比e[i][j]要小即可。e[i][j]表示的是从i号顶点到j号顶点之间的路程。e[i][1]+e[1][j]表示的是从i号顶点先到1号顶点,再从1号顶点到j号顶点的路程之和。其中i是1~n循环,j也是1~n循环
for (i = ; i <= n; i++)
for (j = ; j <= n; j++)
{
if (e[i][j] > e[i][] + e[][j])
e[i][j] = e[i][] + e[][j];
}
在只允许经过1号顶点的情况下,任意两点之间的最短路程更新为

二:接下来继续求在只允许经过1和2号两个顶点的情况下任意两点之间的最短路程,我们需要在只允许经过1号顶点时任意两点的最短路程的结果下,再判断如果经过2号顶点是否可以使得i号顶点到j号顶点之间的路程变得更短。即判断e[i][2]+e[2][j]是否比e[i][j]要小,
//经过1号顶点
for(i=;i<=n;i++)
for(j=;j<=n;j++)
if (e[i][j]>e[i][]+e[][j])
e[i][j]=e[i][]+e[][j]; //经过2号顶点
for(i=;i<=n;i++)
for(j=;j<=n;j++)
if(e[i][j] > e[i][]+e[][j])
e[i][j]=e[i][]+e[][j];
在只允许经过1和2号顶点的情况下,任意两点之间的最短路程更新为:

三:最后允许通过所有顶点作为中转
最开始只允许经过1号顶点进行中转,接下来只允许经过1和2号顶点进行中转……允许经过1~n号所有顶点进行中转,求任意两点之间的最短路程。用一句话概括就是:从i号顶点到j号顶点只经过前k号点的最短路程。
for(k=;k<=n;k++)//允许中转的k个结点
for(i=;i<=n;i++)//源地点i
for(j=;j<=n;j++)//目标地点j
if(e[i][j]>e[i][k]+e[k][j])
e[i][j]=e[i][k]+e[k][j];
code:求固定两地点的最短路径
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; const int INF=0x3f3f;
class Graph
{
private:
int num;
int e;
vector<vector<int> > arr;//存储图的邻接矩阵
vector<int> path;//从v0到其他结点的最短路径
public:
Graph();
void floyd(const int &begin,const int &end);
};
Graph::Graph()
{
cout<<" num"<<endl;
cin>>num;
cout<<" e"<<endl;
cin>>e; path.resize(num); arr.resize(num);
for(int i=;i<num;++i)
arr.at(i).resize(num,INF); cout<<" 边的起始点和终点&&权值"<<endl;
pair<int,int> p;
for(int i=;i<e;++i)
{
cin>>p.first>>p.second;
cin>>arr.at(p.first-).at(p.second-);
}
}
void Graph::floyd(const int &begin,const int &end)
{
//允许经过的中转点;k==0,经过第一个中转点,==1经过第二个中转点(此时已经进过两个中转点
//最多可以经过n个中转点)
for(int k=;k<num;++k)
if(arr.at(begin-).at(end-)>arr.at(begin-).at(k)+arr.at(k).at(end-))
arr.at(begin-).at(end-)=arr.at(begin-).at(k)+arr.at(k).at(end-); cout<<arr.at(begin-).at(end-)<<endl;
}
int main()
{
Graph g;
g.floyd(,);
return ;
}
图的最短路径——dijkstra算法和Floyd算法的更多相关文章
- 最短路径——Dijkstra算法和Floyd算法
Dijkstra算法概述 Dijkstra算法是由荷兰计算机科学家狄克斯特拉(Dijkstra)于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图(无 ...
- 最短路径Dijkstra算法和Floyd算法整理、
转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijks ...
- 【转】最短路径——Dijkstra算法和Floyd算法
[转]最短路径--Dijkstra算法和Floyd算法 标签(空格分隔): 算法 本文是转载,原文在:最短路径-Dijkstra算法和Floyd算法 注意:以下代码 只是描述思路,没有测试过!! Di ...
- 最短路径—Dijkstra算法和Floyd算法
原文链接:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最后边附有我根据文中Dijkstra算法的描述使用jav ...
- 最短路径—Dijkstra算法和Floyd算法【转】
本文来自博客园的文章:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html Dijkstra算法 1.定义概览 Dijk ...
- 【转载】最短路径—Dijkstra算法和Floyd算法
注意:以下代码 只是描述思路,没有测试过!! Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始 ...
- 最短路径—Dijkstra 算法和Floyd 算法
某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多.这让行人很困扰. 现在 ...
- 【转载】Dijkstra算法和Floyd算法的正确性证明
说明: 本文仅提供关于两个算法的正确性的证明,不涉及对算法的过程描述和实现细节 本人算法菜鸟一枚,提供的证明仅是自己的思路,不保证正确,仅供参考,若有错误,欢迎拍砖指正 ----------- ...
- Dijkstra算法和Floyd算法的正确性证明
说明: 本文仅提供关于两个算法的正确性的证明,不涉及对算法的过程描述和实现细节 本人算法菜鸟一枚,提供的证明仅是自己的思路,不保证正确,仅供参考,若有错误,欢迎拍砖指正 ------------- ...
随机推荐
- Win10安装mysql-8.0.11-winx64详细步骤
安装 mysql-8.0.11-winx64 https://blog.csdn.net/qq_20788055/article/details/80372577
- nw.js的localStorage的物理储存位置
前言 因为在做美团外卖商家端的nw.js壳子项目,需要保证在壳子里面使用localStorage的数据可以持久化保存. 发现nw可以保存,即使删除应用重写打包也可以保存,所以解决了这个需求,但是还是需 ...
- Linux文件系统命令 mkdir/rmdir
命令名:mkdir 功能:创建一个文件夹,和touch的区别是,touch是创建一个文件,后面可以跟绝对路径和相对路径 eg: mkdir ren 命令名:rmdir 功能:删除一个文件夹
- C#正则表达式类Match和Group类的理解
正则表达式可以看做一种有特定功能的小型编程语言,在一段文本中定位子字符串.利用正则表达式可以快速地分析大量的文本以找到特定的字符模式:提取.编辑.替换或删除文本子字符串:或将提取的字符串添加到集合.正 ...
- express框架以及配置项
以上命令会将 Express 框架安装在当前目录的 node_modules 目录中, node_modules 目录下会自动创建 express 目录.以下几个重要的模块是需要与 express 框 ...
- js - 如何使子元素阻止继承父元素事件
想要阻止点击 #content 区域时触发a事件,需要在 #content 区域内加入阻止事件冒泡的代码,具体代码如下: <div id="box" onclick=&quo ...
- SAP ABAP: Error Message "Statement already exist" when creating a function module.
https://archive.sap.com/discussions/thread/1089149 First check above link where my problem is so ...
- 推荐系统-07-lambda架构
Lambda 架构 Lambda 架构由Storm的作者Nathan Marz提出,其设计目的在于提供一个能满足大数据系统关键特性的架构,包括高容错.低延迟.可扩展等.其整合离线计算与实时计算,融合不 ...
- PHP目前比较常见的五大运行模式SAPI(转)
运行模式 关于PHP目前比较常见的五大运行模式: 1)CGI(通用网关接口/ Common Gateway Interface) 2)FastCGI(常驻型CGI / Long-Live CGI) 3 ...
- PHP设计模式之工厂模式(转)
概念 工厂模式是我们最常用的实例化对象模式,是用工厂方法代替new操作的一种模式. 使用工厂模式的好处是,如果你想要更改所实例化的类名等,则只需更改该工厂方法内容即可,不需逐一寻找代码中具体实例化的地 ...