(鄰接矩陣)最短路徑算法


 

 

 

 

Floyd算法:

思路 :遍歷計算 i 點 經過 k 點 到 j 點 的最小路徑值 (動態規划思路)

缺點:時間復雜度高,不能解決負邊情況

輸入樣例:

4 8
1 2 2
1 3 6
1 4 4
2 3 3
3 1 7
3 4 1
4 1 5
4 3 12

輸出樣例:

1-->2:2
1-->3:5
1-->4:4
2-->1:9
2-->3:3
2-->4:4
3-->1:6
3-->2:8
3-->4:1
4-->1:5
4-->2:7
4-->3:10

#include <cstdio>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <math.h>
#include <queue>
using namespace std;
const int inf=0x7fffff;
const long long mod=1e9+7;
const double PI=acos(-1);

int n,m,start,end;
int ans=9999999;
bool vis[105];
int e[105][105];

void init(){                           //初始化鄰接矩陣 
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) e[i][j]=0;
            else e[i][j]=inf;
        }
    }
} 

void Floyd(){                                       //思路:依此判斷 i 通過 k 到 j 的最短路 
    for(int k=1;k<=n;k++){                          // k 經轉的節點 
        for(int i=1;i<=n;i++){                      // i 每次的起點 
            for(int j=1;j<=n;j++){                  // j 每次的終點 
                if(k==i&&k==j) continue;
                if(e[i][j]>e[i][k]+e[k][j]){
                    e[i][j]=e[i][k]+e[k][j];
                }
            }
        }
    }
}

int main()
{
    int x,y,value;
    cin>>n>>m;
    init();
    for(int i=0;i<m;i++){
        cin>>x>>y>>value;
        e[x][y]=value;
    }
    Floyd();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) continue;
            cout<<i<<"-->"<<j<<":"<<e[i][j]<<endl;
        }
    } 
    return 0;
}

 Dijkstra算法:

思路:依此找起點可達的點的最小值點。通過最小值點再訪問其他點。不斷更新最小距離。

測試數據:

6 9 1         (6個點9條邊 1為起點)
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4

輸出數據:

1-->1:0
1-->2:1
1-->3:8
1-->4:4
1-->5:13
1-->6:17

#include <cstdio>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <math.h>
#include <queue>
using namespace std;
const int inf=0x7fffff;
const long long mod=1e9+7;
const double PI=acos(-1);

int n,m,start,end;
int ans=9999999;
bool vis[105];
int e[105][105];
void init(){                                //初始化鄰接矩陣 
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) e[i][j]=0;
            else e[i][j]=inf;              //設 inf 為 ∞ 表示兩點不通 
        }
    }
} 
void Dijkstra(int s){                        //Dijkstra算法為單源最短路徑算法 s 為起點 
    int dis[n+1];                           // dis 用來 記錄每次操作時 s 到每個點的最短路徑 
    int minp;                              // 記錄目前操作的最小距離點 
    int min=inf;                     
    
    for(int i=1;i<=n;i++){                 //初始化最短距離數組 dis 
        dis[i]=e[s][i];
    }
    vis[s]=1;                              
    for(int i=1;i<=n;i++){              
        min=inf;
        for(int j=1;j<=n;j++){              //每次找dis數組里面最小未訪問過的值  
            if(min>dis[j]&&!vis[j]){
                min=dis[j];                  //min 表示此時未訪問過的最小距離
                minp=j;                      //minj表示未訪問過的最小距離那個點 
            } 
        }
        vis[minp]=1;                     //設置訪問 
        for(int v=1;v<=n;v++){           //每次訪問 此時與最小值點相連的點v 
            if(e[minp][v]<inf){          //該點可達 
                if(dis[v]>dis[minp]+e[minp][v]){   //s直接到 v 的距離大於 s通過 最小值點到 v 的距離,則更新 
                    dis[v]=dis[minp]+e[minp][v];   
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        cout<<s<<"-->"<<i<<":"<<dis[i]<<endl;   //遍歷 s 到 每個點的最小距離 
    }
}
int main()
{
    int x,y,value,s;
    cin>>n>>m>>s;
    init();
    for(int i=0;i<m;i++){
        cin>>x>>y>>value;
        e[x][y]=value;
    }
    Dijkstra(s);               //s 為起點 
    return 0;
}

 

 Bellman_Floyd算法:

思路:經過n-1次迭代,判斷每次迭代判斷能不能用u[i]-->v[i]

     使源點到v[i]的最短路徑變短。

優點:可以解決帶負邊的問題。

輸入樣例:

5 5 1 (5個點 5條邊 起點1)
2 3 2
1 2 -3
1 5 5
4 5 2
3 4 3

輸出樣例:

0 -3 -1 2 4 (起點到各個點的最短路徑)

#include <cstdio>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <math.h>
#include <vector>
using namespace std;
const int inf=999999;//0x7fffff
const long long mod=1e9+7;
const double PI=acos(-1);

int n,m;
int ans=9999999;
bool vis[105];
int dis[105],u[105],v[105],w[105];
void Bellman_Floyd(int s){
    memset(dis,inf,sizeof(dis));                          //初始 dis最短路徑數組 為無窮 
    dis[s]=0;
    for(int k=1;k<=n-1;k++){                              //迭代 n-1次 更新最短路徑表dis 
        for(int j=1;j<=m;j++){
            dis[v[j]]=min(dis[v[j]],dis[u[j]]+w[j]);      //每次計算能不能由 u[i]到 v[i] 能不能使結果變小並更新 
        }
    }
//    bool ok=0;
//    for(int k=1;k<=m;k++){
//        if(dis[v[k]]>dis[u[k]]+w[k]) ok=1;               //檢測負權回路 
//    }
}
int main()
{
    int x,y,s;
    cin>>n>>m>>s;
    for(int i=1;i<=m;i++){
        cin>>u[i]>>v[i]>>w[i];                           //u[i]邊起使點 v[i]邊指向點 w[i] 權值 
    }
    Bellman_Floyd(s);
    for(int i=1;i<=n;i++){
        cout<<dis[i]<<" ";
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM