最短路径(Floyd算法)


声明:图片及内容基于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

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM