最短路徑—Dijkstra算法


Dijkstra算法

1.定義概覽

Dijkstra(迪傑斯特拉)算法是典型的單源最短路徑算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴展,直到擴展到終點為止。Dijkstra算法是很有代表性的最短路徑算法,在很多專業課程中都作為基本內容有詳細的介紹,如數據結構,圖論,運籌學等等。注意該算法要求圖中不存在負權邊。

問題描述:在無向圖 G=(V,E) 中,假設每條邊 E[i] 的長度為 w[i],找到由頂點 V0 到其余各點的最短路徑。(單源最短路徑)

 

2.算法描述

1)算法思想:設G=(V,E)是一個帶權有向圖,把圖中頂點集合V分成兩組,第一組為已求出最短路徑的頂點集合(用S表示,初始時S中只有一個源點,以后每求得一條最短路徑 , 就將加入到集合S中,直到全部頂點都加入到S中,算法就結束了),第二組為其余未確定最短路徑的頂點集合(用U表示),按最短路徑長度的遞增次序依次把第二組的頂點加入S中。在加入的過程中,總保持從源點v到S中各頂點的最短路徑長度不大於從源點v到U中任何頂點的最短路徑長度。此外,每個頂點對應一個距離,S中的頂點的距離就是從v到此頂點的最短路徑長度,U中的頂點的距離,是從v到此頂點只包括S中的頂點為中間頂點的當前最短路徑長度。

2)算法步驟:

a.初始時,S只包含源點,即S={v},v的距離為0。U包含除v外的其他頂點,即:U={其余頂點},若v與U中頂點u有邊,則<u,v>正常有權值,若u不是v的出邊鄰接點,則<u,v>權值為∞。

b.從U中選取一個距離v最小的頂點k,把k,加入S中(該選定的距離就是v到k的最短路徑長度)。

c.以k為新考慮的中間點,修改U中各頂點的距離;若從源點v到頂點u的距離(經過頂點k)比原來距離(不經過頂點k)短,則修改頂點u的距離值,修改后的距離值的頂點k的距離加上邊上的權。

d.重復步驟b和c直到所有頂點都包含在S中。

 

執行動畫過程如下圖

 模板

編表寫法

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define INF 10000000
#define maxn 3000010
int qd;//到那個點的距離 
int dis[maxn];
int vis[maxn];
int n,m,q,head[maxn];
struct node{
    int u,v,w,next;
}e[maxn];
void add(int u,int v,int w,int i){
    e[i].u=u;//編號為i的對象為u
    if(u==qd) dis[v]=w;//qd到各點的距離//直接入隊 
    e[i].v=v;//編號為i的u的對象為v 
    e[i].w=w;//編號為i的u->v 的距離是w
    e[i].next=head[u];//上一個編號 
    head[u]=i; //記錄現在編號
}
void djc(int u){
    dis[u]=0;vis[u]=1;
    for(int i=2;i<=n;i++){
        int m=INF;
        for(int j=1;j<=n;j++){
            if(!vis[j]&&dis[j]<m){
                u=j;
                m=dis[j];
            }    
        }
        //if(u==qd) break;//沒找到路   
        vis[u]=1;//標記已走過,無論有沒有找到路
        for(int l=head[u];l;l=e[l].next){//當前編號往前找,一直找到0為止,0前再無有效編號 
            if(dis[e[l].v]>dis[e[l].u]+e[l].w){//更新最短路徑
               dis[e[l].v]=dis[e[l].u]+e[l].w;
            }
        }
        
    }
}
int main()
{
    int m,u,v,x,y,z;
    memset(dis,127,sizeof dis);
    scanf("%d%d%d%d",&n,&m,&qd,&v);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z,i);
        add(y,x,z,i+m);
    }
    djc(qd);
    printf("%d\n",dis[v]);//輸出qd->v的最短路徑 
    return 0;
}

 


免責聲明!

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



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