(鄰接表)最短路徑算法


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

輸出樣例:

0 1 8 4 13 17 (源點到各點的最短距離)

#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];
struct node{
    int u;
    int w;
    node(int uu,int ww){
        u=uu;
        w=ww;
    }
};
vector<node> v[105];
void Dijkstra(int s){                        //Dijkstra算法為單源最短路徑算法 s 為起點
    memset(dis,inf,sizeof(dis));             //dis數組表示起點 s 到每個點的最小路徑
    dis[s]=0; 
    int min,minp;
    for(int i=1;i<=n;i++){                 //遍歷dis數組的每一個最短路徑
        min=inf;
        for(int j=1;j<=n;j++){
            if(!vis[j]&&dis[j]<min){       //尋找並記錄此時dis表的最短路徑的值和距離
                min=dis[j];
                minp=j;
            }
        }
        vis[minp]=1;
        for(int u=0;u<v[minp].size();u++){ //尋找此時最短路徑的點可到的點 並更新該點的最短路徑
            node no=v[minp][u];
            if(!vis[no.u]&&dis[no.u]>dis[minp]+no.w){
                dis[no.u]=dis[minp]+no.w;
            }
        }
    }
}
int main()
{
    int x,y,value,s;
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++){
        dis[i]=inf;
    }
    for(int i=0;i<m;i++){
        cin>>x>>y>>value;
        v[x].push_back(node(y,value));
    }
    Dijkstra(s);                        //s 為起點
    for(int i=1;i<=n;i++){              //輸出s 到各個點的最短路徑
        cout<<dis[i]<<" ";
    }
    return 0;
}

 Bellman_Floyd算法:

思路:將起使元素入隊,隊首元素出隊,遍歷隊首元素連接的節點,每次判斷能不能通過隊首元素使起使元素到此時遍歷的節點,使最短路徑變小並更新,到隊列為空為止。

   有點類似於寬度優先搜索,只是寬度優先搜索出隊后不再入隊,該算法需要不斷更新最短路徑,可能需要重新入隊。

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

輸入樣例:

5 7 1     (5個點 7條邊 起點元素1)
1 2 2
1 5 10
2 3 3
2 5 7
3 4 4
4 5 5
5 3 6

輸出樣例:

0 2 5 9 9(起點到各個點的最短路徑)

#include <cstdio>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <math.h>
#include <vector>
#include <queue>

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];

struct node{
    int v;
    int w;
    node(int vv,int ww){
        v=vv;
        w=ww;
    }
}; 

vector<node> v[105];
queue<int> q;

void Bellman_Floyd(int s){
    memset(dis,inf,sizeof(dis));                         //初始化設置所有節點都不可達 
    dis[s]=0;
    vis[s]=1;
    q.push(s); 
    while(!q.empty()){                            
        int no = q.front();                              // no隊首元素序號 nd隊首元素連接節點 
        q.pop();
        for(int i=0;i<v[no].size();i++){                 //每次遍歷隊首節點的連接的節點 判斷通過隊首節點能否使到達連接節點的最短路徑變小並更新 
            node nd=v[no][i];                            
            if(dis[nd.v]>dis[no]+nd.w){
                dis[nd.v]=dis[no]+nd.w;
                if(!vis[nd.v]){                         //此時隊首相連節點不在隊列中 需要添加隊列中並置為訪問 
                    vis[nd.v]=1;
                    q.push(nd.v);
                }
            }
        }
     vis[no]=0; } }
int main() { int x,y,value,s; cin>>n>>m>>s; for(int i=1;i<=m;i++){ cin>>x>>y>>value; v[x].push_back(node(y,value)); } Bellman_Floyd(s); for(int i=1;i<=n;i++){ cout<<dis[i]<<" "; } return 0; }

 

 

 


免責聲明!

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



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