1. 程式人生 > >洛谷P3371單源最短路徑SPFA算法

洛谷P3371單源最短路徑SPFA算法

開始 編程 using space 並且 shu 理解 前向星 來講

SPFA同樣是一種基於貪心的算法,看過之前一篇blog的讀者應該可以發現,SPFA和堆優化版的Dijkstra如此的相似,沒錯,但SPFA有一優點是Dijkstra沒有的,就是它可以處理負邊的情況。

和Dijkstra的出發點不同,Dijkstra是從點入手的,而SPFA則是從邊開始的,要不斷的改變邊,把點入堆,有的時候SPFA是比堆優化版的Dijkstra要慢的。

下面是程序,還是借助它來講解,很容易理解,關鍵之處是一定要自己去試著編程。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct node{
 4     int
quan,qian,to; 5 }shu[500010]; 6 int head[10010],ans,n,m,s,dis[10010]; 7 bool vis[10010]; 8 priority_queue<int> q; 9 void add(int x,int y,int z){ 10 shu[++ans].qian=head[x]; 11 shu[ans].quan=z; 12 shu[ans].to=y; 13 head[x]=ans; 14 }//鏈式前向星存儲(前2篇中已經講到) 15 void spfa(){ 16 memset(dis,0x3f
,sizeof(dis)); 17 memset(vis,false,sizeof(vis)); 18 q.push(s);//s入堆 19 dis[s]=0;vis[s]=true;//s已經在堆中可以從此查找 20 while (q.size()!=0){//如果堆中元素個數不為0那麽還可以繼續 21 int x=q.top();q.pop();//x為要查找的編號 22 vis[x]=false;//已經查找過了,但以後有可能還要更新,所以把它還原 23 int w=head[x]; 24 while (w!=0){ 25
if (shu[w].quan+dis[x]<dis[shu[w].to]){//更新到shu[w].to這個點的最小值 26 dis[shu[w].to]=shu[w].quan+dis[x]; 27 if (not vis[shu[w].to]) q.push(shu[w].to);//如果更新了,並且不在堆中,那麽就入堆 28 } 29 w=shu[w].qian; 30 } 31 } 32 } 33 int main(){ 34 cin>>n>>m>>s; 35 ans=0; 36 for (int i=1;i<=m;i++){ 37 int a,b,c; 38 cin>>a>>b>>c; 39 add(a,b,c);//存邊 40 } 41 spfa(); 42 for (int i=1;i<=n;i++){ 43 if (dis[i]>=100000) cout<<"2147483647 "; 44 else cout<<dis[i]<<" "; 45 } 46 }

個人覺得不用優先隊列,直接用普通的隊列也是可以解決問題的。

洛谷P3371單源最短路徑SPFA算法