多源最短路徑Floyd演算法實戰練習

多源最短路徑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 - LeetCode?

leetcode.com圖標

Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0.

Example:

Given a / b = 2.0, b / c = 3.0.

queries are: 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, where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector<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題

TAG:C | 演算法 | LeetCode |