Dijkstra算法 (迪傑斯特拉)

定義

  Dijkstra(迪傑斯特拉)算法是典型的單源最短路徑算法,用於計算一個節點到其餘全部節點的最短路徑。主要特色是以起始點爲中心向外層層擴展,直到擴展到終點爲止。node

原理

  設圖 G=(V,E) 全部頂點的集合爲 V,起點爲 S,最短路徑樹中包含的頂點集合爲 S。在各計算步驟中,咱們將選出最短路徑樹的邊和頂點並將其添加至S。c++

  對於各頂點 i,設僅經由S內的頂點的 s 到 i 的最短路徑成本爲 d[i], i 在最短路徑樹中的父節點爲 p[i]。算法

  ①初始狀態下將 S 置空。優化

      初始化 s 的 d[s]=0;除 s 外,全部屬於 V 的頂點 i 的 d[i]=∞。spa

  ②循環進行下述處理,直至 S=V 爲止。設計

      從 V-S 中選出 d[u] 最小的頂點 u。code

     將 u 添加至 S,同時將與 u 相鄰且屬於 V-S 的全部頂點 v 的值按照下述方式更新blog

     if(d[u] + w(u,v) < d[v])隊列

        d[v] = d[u] + w(u,v) , p[v] = u ;it

  ❗ 顯然迪傑斯特拉算法並不能處理負權圖。下圖中A->B的最短路應爲 3=8-5,但用此算法算出來的A->B的最短路爲7。

 

  迪傑斯特拉最短路徑算法和普利姆算法賊像。:)

實現

 

 

 

原算法

#include<bits/stdc++.h> using namespace std; const int maxn=1005; const int inf=0x3f3f3f3f; struct node { int v,w; node(){} node(int a,int b) {v=a;w=b;} }; vector<node> e[maxn]; int n,m; void dij(); int main() { int i,u,v,w; scanf("%d%d",&n,&m); for(i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); e[u].push_back(node(v,w)); } dij(); system("pause"); return 0; } void dij() { int dis[maxn],vis[maxn]={0},i,j,mmin,f; fill(dis,dis+maxn,inf); dis[1]=0; for(i=1;i<=n;i++) { mmin=inf; for(j=1;j<=n;j++) if(!vis[j]&&dis[j]<mmin) mmin=dis[f=j]; vis[f]=1; for(j=0;j<e[f].size();j++) { if(dis[e[f][j].v]>dis[f]+e[f][j].w) dis[e[f][j].v]=dis[f]+e[f][j].w; } } for(j=1;j<=n;j++) printf("1->%d %d\n",j,dis[j]); }

優先隊列優化

#include<bits/stdc++.h> using namespace std; const int maxn=1005; const int inf=0x3f3f3f3f; struct node { int v,w; node(){} node(int a,int b) {v=a;w=b;} bool operator <(const node &n) const {return w>n.w;} }; vector<node> e[maxn]; int n,m; void dij_queue(); int main() { int i,u,v,w; scanf("%d%d",&n,&m); for(i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); e[u].push_back(node(v,w)); } dij_queue(); system("pause"); return 0; } void dij_queue() { int dis[maxn],vis[maxn]={0},u,v,w,i; node p; priority_queue<node> que; que.push(node(1,0)); fill(dis,dis+maxn,inf); dis[1]=0; while(!que.empty()) { p=que.top();que.pop(); u=p.v; if(vis[u]) continue; vis[u]=1; for(i=0;i<e[u].size();i++) { w=e[u][i].w;v=e[u][i].v; if(!vis[v]&&dis[v]>dis[u]+w) { dis[v]=dis[u]+w; que.push(node(v,dis[v])); } } } for(i=1;i<=n;i++) printf("1->%d %d\n",i,dis[i]); }

挑戰程序設計競賽(第2版)

相關文章
相關標籤/搜索