1. 程式人生 > 其它 >圖論:Ford 演算法 求最短路徑

圖論:Ford 演算法 求最短路徑

Ford 演算法 求最短路徑   先構建鄰接表陣列和初始化鄰接關係
 int v1[maxn],v2[maxn],w[maxn];//記錄起點終點和權值
    for(int i=1;i<=m;++i)
    {
        cin>>u>>v>>val;
        v1[i]=u;
        v2[i]=v;
        w[i]=val;
    }

  構建一維陣列d,記錄距離出發點的距離,d[出發點]初始化為0,自己和自己的距離為0,其他點和出發點的d先初始化為oo,並且構建pre陣列,便於遞迴輸出最短路徑。出發點的前驅結點設為0,代表出發點沒有前驅結點,也是一會遞迴輸出路徑的退出條件。

int d[maxn],pre[maxn];//記錄距離出發點的距離 和最短路徑的前驅結點
for(int i=0;i<=n;++i)d[i]=0x7fffff;//先初始化為oo 很大的值
 d[s]=0;//自己到自己的距離為0;
    pre[s]=0;

  核心演算法程式碼就是一個二維陣列,外層迴圈n-1次,內層迴圈m次,內層是迴圈m個鄰接關係,每次更新d,外層迴圈n-1次,是剛好迴圈n-1次可以把所有點到起點的最短距離更新完。內層迴圈中,定義起點為u,終點為v,進行兩個if判斷,①:如果d[u]+邊權<d[v]就更新d[v],就是更新v到起點的距離,②:如果d[v]+邊權<d[u] 就更新起點到u的距離。注意兩次更新中,如果有更新,都要改變pre陣列,像第一次if 如果更新,就說明起點到u 再到 v的路徑更短,所以 v的前驅是u 更新pre[v]=u,後面同理。 

for(int i=1;i<=n-1;++i)//最多n-1次
        for(int j=1;j<=m;++j)
        {
            u=v1[j],v=v2[j];
            if(d[u]+w[j]<d[v])
            {
                d[v]=d[u]+w[j];
                pre[v]=u;
            }

            if(d[v]+w[j]<d[u])
            {
                d[u]=d[v]+w[j];
                pre[u]
=v; } }

輸出路徑的遞迴函式:

void print(int i)//遞迴輸出路徑程式碼
{
    if(pre[i])
    print(pre[i]);
    cout<<i<<" ";
}

完整程式碼:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100;
int v1[maxn],v2[maxn],w[maxn];//記錄起點終點和權值
int d[maxn],pre[maxn];//記錄距離出發點的距離 和最短路徑的前驅結點
int n,m,s;//n個結點 m條邊 s為出發點
int u,v,val;//起點和終點
void print(int i)//遞迴輸出路徑程式碼
{
    if(pre[i])
    print(pre[i]);
    cout<<i<<" ";
}
int main()
{
    cin>>n>>m>>s;
    for(int i=0;i<=n;++i)d[i]=0x7fffff;//先初始化為oo 很大的值
    for(int i=1;i<=m;++i)
    {
        cin>>u>>v>>val;
        v1[i]=u;
        v2[i]=v;
        w[i]=val;
    }
    d[s]=0;//自己到自己的距離為0;
    pre[s]=0;
    for(int i=1;i<=n-1;++i)//最多n-1次
        for(int j=1;j<=m;++j)
        {
            u=v1[j],v=v2[j];
            if(d[u]+w[j]<d[v])
            {
                d[v]=d[u]+w[j];
                pre[v]=u;
            }

            if(d[v]+w[j]<d[u])
            {
                d[u]=d[v]+w[j];
                pre[u]=v;
            }
        }
    for (int i = 1; i <= n; ++i)
    {
        cout << d[i] << endl;
        print(i);
    }
    
    return 0;
}