最短路徑(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