声明:图片及内容基于https://www.bilibili.com/video/BV1oa4y1e7Qt?from=articleDetail

多源最短路径的引入

Floyd算法

原理

加入a:

加入b:

加入c:

数据结构

核心代码

Floyd()

void MGraph::Floyd(){
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
dist[i][j]=arc[i][j]; //dist数组初始化
if(dist[i][j]!=INFINIT&&dist[i][j]!=0) //dist为INFINIT则无路径,dist为0则指向自己
path[i][j]=vertex[i]+vertex[j]; //path数组初始化
else
path[i][j]=""; //不符合则path为空串
}
}
for(int k=0;k<vertexNum;k++){ //k个顶点循环k次
for(int i=0;i<vertexNum;i++){ //k每循环一次,要更新dist和path数组
for(int j=0;j<vertexNum;j++){
if(dist[i][k]+dist[k][j]<dist[i][j]){
dist[i][j]=dist[i][k]+dist[k][j];
//这里两个path拼接的时候,第一个字符串的最后一个字符和第二个字符串的第一个字符重复
//用substr去除第一个字符串的最后一个字符
string tmp=path[i][k].substr(0,path[i][k].length()-1);
path[i][j]=tmp+path[k][j];
}
}
}
}
displayDist();
displayPath();
}

完整代码

#include<iostream>
#define MAX 50
#define INFINIT 65535
#include <string>
using namespace std;
class MGraph{
private:
int vertexNum,arcNum; //顶点数,边数
int arc[MAX][MAX]; //邻接矩阵
string vertex[MAX]; //顶点信息
int dist[MAX][MAX];
string path[MAX][MAX];
public:
MGraph(string v[],int n,int e);
void display();
void Floyd();
void displayDist();
void displayPath();
};
void MGraph::Floyd(){
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
dist[i][j]=arc[i][j]; //dist数组初始化
if(dist[i][j]!=INFINIT&&dist[i][j]!=0) //dist为INFINIT则无路径,dist为0则指向自己
path[i][j]=vertex[i]+vertex[j]; //path数组初始化
else
path[i][j]=""; //不符合则path为空串
}
}
for(int k=0;k<vertexNum;k++){ //k个顶点循环k次
for(int i=0;i<vertexNum;i++){ //k每循环一次,要更新dist和path数组
for(int j=0;j<vertexNum;j++){
if(dist[i][k]+dist[k][j]<dist[i][j]){
dist[i][j]=dist[i][k]+dist[k][j];
//这里两个path拼接的时候,第一个字符串的最后一个字符和第二个字符串的第一个字符重复
//用substr去除第一个字符串的最后一个字符
string tmp=path[i][k].substr(0,path[i][k].length()-1);
path[i][j]=tmp+path[k][j];
}
}
}
}
displayDist();
displayPath();
}
void MGraph::displayDist(){ //打印dist数组
cout<<"dist数组:"<<endl;
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
cout<<dist[i][j]<<"\t";
}
cout<<endl;
}
}
void MGraph::displayPath(){ //打印path数组
cout<<"path数组:" <<endl;
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
cout<<path[i][j]<<"\t";
}
cout<<endl;
}
}
MGraph::MGraph(string v[],int n,int e){ //n是顶点数,e是边数
vertexNum=n;
arcNum=e;
for(int i=0;i<vertexNum;i++){
vertex[i]=v[i];
}
for(int i=0;i<arcNum;i++){ //初始化邻接矩阵
for(int j=0;j<arcNum;j++){
if(i==j) arc[i][j]=0;
else arc[i][j]=INFINIT;
}
}
int vi,vj,w;
for(int i=0;i<arcNum;i++){
cout<<"请输入有向边的两个顶点和这条边的权值"<<endl;
cin>>vi>>vj>>w; //输入边依附的两个顶点的编号 和权值
arc[vi][vj]=w; //有边标志
}
}
void MGraph::display(){
cout<<"邻接矩阵:"<<endl;
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
if(arc[i][j]==INFINIT)
cout<<"∞"<<"\t";
else cout<<arc[i][j]<<"\t";
}
cout<<endl;
}
cout<<endl;
cout<<"结点信息:"<<endl;
for(int i=0;i<vertexNum;i++){
cout<<vertex[i]<<" ";
}
cout<<endl;
}
int main(){
int n,e;
string v[MAX];
cout<<"请输入顶点数和边数"<<endl;
cin>>n>>e;
cout<<"请输入顶点信息"<<endl;
for(int i=0;i<n;i++){
cin>>v[i];
}
MGraph mgraph(v,n,e);
mgraph.display();
mgraph.Floyd();
return 0;
}

输入:

3 5
a b c
0 1 4
0 2 11
1 0 6
1 2 2
2 0 3

输出:

邻接矩阵:
0 4 11
6 0 2
3 ∞ 0

结点信息:
a b c
dist数组:
0 4 6
5 0 2
3 7 0
path数组:
   ab   abc
bca       bc
ca   cab

例题:娱乐中心选址

#include<iostream>
#define MAX 50
#define INFINIT 65535
#include <string>
using namespace std;
class MGraph{
private:
int vertexNum,arcNum; //顶点数,边数
int arc[MAX][MAX]; //邻接矩阵
string vertex[MAX]; //顶点信息
int dist[MAX][MAX];
string path[MAX][MAX];
int rowSum[MAX];
int rowMax[MAX];
public:
MGraph(string v[],int n,int e);
void display();
void Floyd();
void displayDist();
void displayPath();
void bestCentralAmusement();
void displayRowMax();
void displayRowSum();
};
void MGraph::bestCentralAmusement(){
for(int i=0;i<vertexNum;i++)
rowSum[i]=0;
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
rowSum[i]+=dist[i][j];
}
}
int tmp;
for(int i=0;i<vertexNum;i++){
tmp=0;
for(int j=0;j<vertexNum;j++){
if(tmp<dist[i][j]) tmp=dist[i][j];
}
rowMax[i]=tmp;
}
int tmp2=INFINIT;
int index=-1;
for(int i=0;i<vertexNum;i++){
if(rowMax[i]<tmp2){
tmp2=rowMax[i];
index=i;
}
if(tmp2==rowMax[i]){
if(rowSum[i]<tmp2){
index=i;
}else{
;
}
}
}
displayRowMax();
displayRowSum();
cout<<"index:"<<index<<endl;
cout<<"最合适的位置是"<<vertex[index]<<endl;
}
void MGraph::displayRowSum(){
cout<<"rowSum: "<<endl;
for(int i=0;i<vertexNum;i++)
cout<<rowSum[i]<<" ";
cout<<endl;
}
void MGraph::displayRowMax(){
cout<<"rowMax:"<<endl;
for(int j=0;j<vertexNum;j++)
cout<<rowMax[j]<<" ";
cout<<endl;
}
void MGraph::Floyd(){
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
dist[i][j]=arc[i][j]; //dist数组初始化
if(dist[i][j]!=INFINIT&&dist[i][j]!=0) //dist为INFINIT则无路径,dist为0则指向自己
path[i][j]=vertex[i]+vertex[j]; //path数组初始化
else
path[i][j]=""; //不符合则path为空串
}
}
for(int k=0;k<vertexNum;k++){ //k个顶点循环k次
for(int i=0;i<vertexNum;i++){ //k每循环一次,要更新dist和path数组
for(int j=0;j<vertexNum;j++){
if(dist[i][k]+dist[k][j]<dist[i][j]){
dist[i][j]=dist[i][k]+dist[k][j];
//这里两个path拼接的时候,第一个字符串的最后一个字符和第二个字符串的第一个字符重复
//用substr去除第一个字符串的最后一个字符
string tmp=path[i][k].substr(0,path[i][k].length()-1);
path[i][j]=tmp+path[k][j];
}
}
}
}
displayDist();
displayPath();
}
void MGraph::displayDist(){ //打印dist数组
cout<<"dist数组:"<<endl;
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
cout<<dist[i][j]<<"\t";
}
cout<<endl;
}
}
void MGraph::displayPath(){ //打印path数组
cout<<"path数组:" <<endl;
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
cout<<path[i][j]<<"\t";
}
cout<<endl;
}
}
MGraph::MGraph(string v[],int n,int e){ //n是顶点数,e是边数
vertexNum=n;
arcNum=e;
for(int i=0;i<vertexNum;i++){
vertex[i]=v[i];
}
for(int i=0;i<arcNum;i++){ //初始化邻接矩阵
for(int j=0;j<arcNum;j++){
if(i==j) arc[i][j]=0;
else arc[i][j]=INFINIT;
}
}
int vi,vj,w;
for(int i=0;i<arcNum;i++){
cout<<"请输入有向边的两个顶点和这条边的权值"<<endl;
cin>>vi>>vj>>w; //输入边依附的两个顶点的编号 和权值
arc[vi][vj]=w; //有边标志
}
}
void MGraph::display(){
cout<<"邻接矩阵:"<<endl;
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
if(arc[i][j]==INFINIT)
cout<<"∞"<<"\t";
else cout<<arc[i][j]<<"\t";
}
cout<<endl;
}
cout<<endl;
cout<<"结点信息:"<<endl;
for(int i=0;i<vertexNum;i++){
cout<<vertex[i]<<" ";
}
cout<<endl;
}
int main(){
int n,e;
string v[MAX];
cout<<"请输入顶点数和边数"<<endl;
cin>>n>>e;
cout<<"请输入顶点信息"<<endl;
for(int i=0;i<n;i++){
cin>>v[i];
}
MGraph mgraph(v,n,e);
mgraph.display();
mgraph.Floyd();
mgraph.bestCentralAmusement();
return 0;
}

输入:

5 10
a b c d e
0 1 13
0 3 4
1 0 13
1 2 15
1 4 5
2 3 12
3 0 4
3 2 12
4 2 6
4 3 3

输出:

邻接矩阵:
0   13 ∞  4  ∞
13  0 15 ∞  5
∞  ∞  0  12 ∞
4  ∞  12  0  ∞
∞  ∞  6   3  0

结点信息:
a b c d e
dist数组:
0  13  16  4 18
12  0  11  8  5
16 29  0 12 34
4  17  12 0  22
7  20   6  3  0
path数组:
ab adc ad abe
beda bec bed be
cda cdab cd cdabe
da dab dc dabe
eda edab ec ed
rowMax:
18 12 34 22 20
rowSum:
51 36 91 55 36
index:1
最合适的位置是b

最短路径(Floyd算法)的更多相关文章

  1. 单源最短路径Dijkstra算法,多源最短路径Floyd算法

    1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...

  2. 7-8 哈利·波特的考试(25 分)(图的最短路径Floyd算法)

    7-8 哈利·波特的考试(25 分) 哈利·波特要考试了,他需要你的帮助.这门课学的是用魔咒将一种动物变成另一种动物的本事.例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等.反方向变 ...

  3. 最短路径(Floyd)算法

    #include <stdio.h>#include <stdlib.h>/* Floyd算法 */#define VNUM 5#define MV 65536int P[VN ...

  4. 单源最短路径——Floyd算法

    正如我们所知道的,Floyd算法用于求最短路径.Floyd算法可以说是Warshall算法的扩展,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3). Floyd算法的基本思想如下:从任意 ...

  5. 最短路径Floyd算法【图文详解】

    Floyd算法 1.定义概览 Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被 ...

  6. 【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?

    简介 Floyd-Warshall算法(Floyd-Warshall algorithm),是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以 ...

  7. 图论之最短路径floyd算法

    Floyd算法是图论中经典的多源最短路径算法,即求任意两点之间的最短路径. 它可采用动态规划思想,因为它满足最优子结构性质,即最短路径序列的子序列也是最短路径. 举例说明最优子结构性质,上图中1号到5 ...

  8. 最短路径—Floyd算法

    Floyd算法 所有顶点对之间的最短路径问题是:对于给定的有向网络G=(V,E),要对G中任意两个顶点v,w(v不等于w),找出v到w的最短路径.当然我们可以n次执行DIJKSTRA算法,用FLOYD ...

  9. 最短路径——Floyd算法(含证明)

    通过dij,ford,spfa等算法可以快速的得到单源点的最短路径,如果想要得到图中任意两点之间的最短路径,当然可以选择做n遍的dij或是ford,但还有一个思维量较小的选择,就是floyd算法. 多 ...

  10. 多源最短路径Floyd算法

    多源最短路径是求图中任意两点间的最短路,采用动态规划算法,也称为Floyd算法.将顶点编号为0,1,2...n-1首先定义dis[i][j][k]为顶点 i 到 j 的最短路径,且这条路径只经过最大编 ...

随机推荐

  1. How to enable HTTPS for local development in macOS using Chrome

    How to enable HTTPS for local development in macOS using Chrome HTTPS, macOS, Chrome local HTTPS htt ...

  2. js 监听ajax请求

    function hookSend(hook) { if (!XMLHttpRequest.prototype._oldSend) XMLHttpRequest.prototype._oldSend ...

  3. Flutter 使用高德地图定位

    amap_location 包 获取debug SHA1 // 使用debug.keystore获取debug SHA1 C:\Users\ajanuw\.android>keytool -li ...

  4. windows(wsl)下的trino编译和升级注意事项

    最近在进行旧版本的prestosql和prestodb升级相关的操作,尝试自己编译了一下,这里记录一下过程和遇到问题的处理. 因为Trino不支持windows下的编译,如果使用windows最方便的 ...

  5. 移动端时间回显iphone出现的问题

    new Date(item.startTime.replace(/-/g, '/') dateFormat('hh:mm', new Date(item.startTime.replace(/-/g, ...

  6. Yarn框架的一般过程

    基本过程图: Clinet向ResouceManager发送Job请求 ResouceManager接受到请求后在自身开启一个Container 来运行的ApplicationManager组件,Ap ...

  7. java中是否存在i+1<i?

    存在! 首先我们知道int的取值范围是: -2147483648~2147483647,最高位为符号位 2147483647的二进制为:01111111 11111111 11111111 11111 ...

  8. the import java.util cannot be resolve

    重新配置一下build path 的jre,如果不行的话就重新设置jre(在add library中installed JREs)

  9. Vue框架:vue-cookies组件

    目录 一.vue-cookies简介 二.vue-cookies安装与配置 三.vue-cookies的使用 一.vue-cookies简介 vue-cookies组件是vue框架用来操作浏览器coo ...

  10. 微信小程序切换标签改变样式

    微信小程序切换标签改变样式 wxml <!--顶部导航栏--> <view class="swiper-tab"> <view class=" ...