多源最短路徑Floyd演算法實戰練習
來自專欄 如何快速高效學習C++?
一、演算法原理
Floyd演算法的核心思想在於,利用動態規劃的思想,將圖中每一個點,作為「中轉站」來優化圖中其他任意兩點之間的距離,將點1作為中轉站時:
for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if ( e[i][j] > e[i][1]+e[1][j] ) e[i][j] = e[i][1]+e[1][j]; } }
同樣的,將圖中每一個點作為「中轉站」可以表示為:
for(k=1;k<=n;k++)//「中轉站1~k」 for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(e[i][j]>e[i][k]+e[k][j])//e為鄰接表 e[i][j]=e[i][k]+e[k][j];
以上即Floyd演算法完整的代碼。
更詳細的介紹可參考:演算法 6:只有五行的 Floyd 最短路演算法
二、Floyd演算法實戰練習
LeetCode:399. Evaluate Division
Evaluate Division - LeetCodeEquations are given in the format
Example:A / B = k
, whereA
andB
are variables represented as strings, andk
is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return-1.0
.Given
queries are:a / b = 2.0, b / c = 3.0.
a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return[6.0, 0.5, -1.0, 1.0, -1.0 ].
The input is:vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries
, whereequations.size() == values.size()
, and the values are positive. This represents the equations. Returnvector<double>
.According to the example above:equations = [ ["a", "b"], ["b", "c"] ],
values = [2.0, 3.0],queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]. The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.
完整AC代碼+詳細注釋
class Solution {public: vector<double> calcEquation(vector<pair<string, string>> e, vector<double>& val, vector<pair<string, string>> q) { #define um unordered_map//簡化代碼 #define us unordered_set um<string,um<string,double>>G;//鄰接表 us<string>S;//用於出現的每一個變數名稱 for(int i=0;i<(int)e.size();i++){ string a=e[i].first,b=e[i].second; G[a][b]=val[i]; G[b][a]=1/val[i]; S.insert(a);S.insert(b); } //floyd演算法核心部分 for(auto &s:S)G[s][s]=1.0; for(auto&k:S){ for(auto&i:S){ for(auto&j:S){ //鄰接表的優化 if(0==G[i][j]&&0!=G[i][k]&&0!=G[k][j]){ G[i][j]=G[i][k]*G[k][j]; } } } } /*//另外一種遍歷方式,不夠簡潔,但速度更快。 for(auto it=S.begin();it!=S.end();it++){ for(auto i=S.begin();i!=S.end();i++){ for(auto j=S.begin();j!=S.end();j++){ if(0==G[*i][*j]&&G[*i][*it]!=0&&G[*it][*j]!=0){ G[*i][*j]=G[*i][*it]*G[*it][*j]; } } } }*/ //構造結果返回 vector<double>res; for(int i=0;i<(int)q.size();i++){ double temp=G[q[i].first][q[i].second]; res.push_back(0==temp?-1:temp); } return res; }};
PS:
廣告時間啦~
理工狗不想被人文素養拖後腿?不妨關注微信公眾號:
推薦閱讀:
※029 Divide Two Integers[M]
※LeetCode的一個bug?
※雙端隊列
※[leetcode algorithms]題目11
※Leetcode 簡略題解 - 共567題