3371 【模板】單源最短路徑

來源:互聯網
上載者:User

標籤:有用   vector   queue   表示   cout   clear   不能   resize   目標   

題目描述

如題,給出一個有向圖,請輸出從某一點出發到所有點的最短路徑長度。

輸入輸出格式

輸入格式:

第一行包含三個整數N、M、S,分別表示點的個數、有向邊的個數、出發點的編號。

接下來M行每行包含三個整數Fi、Gi、Wi,分別表示第i條有向邊的出發點、目標點和長度。

 

輸出格式:

一行,包含N個用空格分隔的整數,其中第i個整數表示從點S出發到點i的最短路徑長度(若S=i則最短路徑長度為0,若從點S無法到達點i,則最短路徑長度為2147483647)

代碼:

 1 #include<iostream> 2 #include<algorithm> 3 #include<queue> 4 using namespace std; 5 struct edge{ 6     int k;//終點  7     int w;//邊權  8     //node(int kk, int ww):k(kk), w(ww){} 9 };10 bool operator <(const edge&n1, const edge&n2){11     return n1.w>n2.w;12 }13 priority_queue<edge>pq;14 vector<vector<edge> >v;15 const int inf = 2147483647;16 bool used[10010];17 int d[10010];18 19 int main(){20     int n, m, s;21     cin>>n>>m>>s;22     v.clear();23     v.resize(m+1);24     int i, j;25     edge p;//(0, 0);26     for(i = 1; i <= m; i++){27         int a, b, c;28         cin>>a>>b>>c;29         p.k = b;30         p.w = c;31         v[a].push_back(p);32     }33     for(i = 1; i <= n; i++) d[i] = inf;34     d[s] = 0;35     p.k = s;36     p.w = 0;37     pq.push(p);38     while(!pq.empty()){39         p = pq.top();40         pq.pop();41         if(used[p.k])//已經求出了最短路 42             continue;43         used[p.k] = true;44         d[p.k] = p.w;45         for(i = 0; i < v[p.k].size(); i++){46             edge q;47             q.k = v[p.k][i].k;48             if(!used[q.k]&&d[q.k]>p.w+v[p.k][i].w){49                 q.w = p.w + v[p.k][i].w;50                 pq.push(q);51             }52         } 53     } 54     for(i=1; i<=n; i++)55         cout<<d[i]<<" ";56     return 0;57 } 

備忘:

加堆最佳化的dijkstra模板。開始是照著gw的ppt寫的,然後瞪了一個小時也沒看懂for迴圈裡面那幾行,已經覺得人生絕望了。zmj幫我把程式改成了現在這樣便於理解的狀態,現在我要繼續解析一下,邊寫邊想。

用vector<vector<edge>>存圖,結構體表示一條邊,元素包括邊權和終點編號。d[i]表示從源點到編號為i的點的最短距離。

首先把源點push進堆。然後進入while迴圈。

加堆是如何?最佳化的呢?就是因為堆頂元素自動就是最近的元素。

取堆頂元素p(按照定義,這時p邊所連的點p.k是堆裡w最小,即距離“已選點集”最近的點),將p彈出(必須現在彈出,不能鬆弛完了再彈)。如果發現p.k是已經用過的點了,則跳過。如果是一個新的點,則將其標記。(pop出的點集就是“已選點集,他們全都used過了)

哎呀,寫出來果然清楚多了。因為現在p.k是距離已選點集最近的點,所以它的d值其實已經確定了,於是更新(現在的d就是最終結果)。事實上現在p.k已經是我們選中的點了(即加入點集),接下來做的就是鬆弛跟它相連的點。

依次遍曆與p.k相連的點,即q.k,如果q.k沒有用過,並且d值比新路徑大,則更新q.w(為什麼不更新d值?因為這時d值還沒有確定,當然更新也是可以的,但沒這個必要。因為當它彈出去時的w值就是最終的d值,所以在這裡只更新q.w就可以了),更新完了就把它push進堆,這樣下一輪好直接取堆頂元素。

靠,我現在終於想明白了!為什麼gw要那麼寫。因為d值在這裡實際上一直是無窮大啊。所以這句根本是廢話。彈出去的時候再更新就直接是最終的結果了啊。

再補充一句,為什麼可以不用比較就直接給q.w賦值。因為賦值完了都是要把新q push進堆裡的,我們總是取堆裡最小的,所以那些不夠小的push進去根本就無所謂,到時候就又都原封不動地彈出來了。

這個道理我tm想了一下午。寫部落格真是有奇效。

好了,我要附上gw的原代碼寫法了。orz

 1 #include<iostream> 2 #include<algorithm> 3 #include<queue> 4 using namespace std; 5 struct edge{ 6     int k;//終點  7     int w;//邊權  8     //node(int kk, int ww):k(kk), w(ww){} 9 };10 bool operator <(const edge&n1, const edge&n2){11     return n1.w>n2.w;12 }13 priority_queue<edge>pq;14 vector<vector<edge> >v;15 const int inf = 2147483647;16 bool used[10010];17 int d[10010];18 19 int main(){20     int n, m, s;21     cin>>n>>m>>s;22     v.clear();23     v.resize(m+1);24     int i, j;25     edge p;//(0, 0);26     for(i = 1; i <= m; i++){27         int a, b, c;28         cin>>a>>b>>c;29         p.k = b;30         p.w = c;31         v[a].push_back(p);32     }33     for(i = 1; i <= n; i++) d[i] = inf;34     d[s] = 0;35     p.k = s;36     p.w = 0;37     pq.push(p);38     while(!pq.empty()){39         p = pq.top();40         pq.pop();41         if(used[p.k])//已經求出了最短路 42             continue;43         used[p.k] = true;44         d[p.k] = p.w;45         for(i = 0; i < v[p.k].size(); i++){46             edge q;47             q.k = v[p.k][i].k;48             if(used[q.k])continue;49             q.w = p.w + v[p.k][i].w;50             pq.push(q);51         } 52     } 53     for(i=1; i<=n; i++)54         cout<<d[i]<<" ";55     return 0;56 } 

相信這一下午沒有白費,對dijkstra的理解應該還是很深刻的(這樣安慰自己)。

3371 【模板】單源最短路徑

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.