原題連接 https://www.luogu.org/problemnew/show/P1744ios
一道最短路的模板題.....很簡單吧算法
求最短路的方法有不少,可是對於剛學完Floyd的我,只會用這個.......雖然有點慢,可是也能AC數組
Floyd算法閉包
1.定義概覽spa
Floyd-Warshall算法(Floyd-Warshall algorithm)是解決任意兩點間的最短路徑的一種算法,能夠正確處理有向圖或負權的最短路徑問題,同時也被用於計算有向圖的傳遞閉包。Floyd-Warshall算法的時間複雜度爲O(N3),空間複雜度爲O(N2)。code
2.算法描述blog
算法思想原理:ci
Floyd算法是一個經典的動態規劃算法。用通俗的語言來描述的話,首先咱們的目標是尋找從點i到點j的最短路徑。從動態規劃的角度看問題,咱們須要爲這個目標從新作一個詮釋(這個詮釋正是動態規劃最富創造力的精華所在)string
從任意節點i到任意節點j的最短路徑不外乎2種可能,1是直接從i到j,2是從i通過若干個節點k到j。因此,咱們假設Dis(i,j)爲節點u到節點v的最短路徑的距離,對於每個節點k,咱們檢查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,若是成立,證實從i到k再到j的路徑比i直接到j的路徑短,咱們便設置Dis(i,j) = Dis(i,k) + Dis(k,j),這樣一來,當咱們遍歷完全部節點k,Dis(i,j)中記錄的即是i到j的最短路徑的距離。it
咱們能夠開一個n*n的鄰接矩陣,記錄聯通狀況:f[i][j]若是爲1,則說明i到j聯通;若是爲∞,則說明不連通(之因此用∞的緣由是比較的時候無窮大必定比任何除無窮大之外的數的和都大,這樣就不會把∞算進去),而後能夠進一步將f[i][j]=1的地方利用兩點間距離公式將1換成具體的距離
代碼以下:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; int n,m,x,y,a[101][2],aa,bb; //a數組存放座標 double b[101][101]; //b數組存放最短路,注意double類型 int main() { cin>>n; //n個點 for(int i=1;i<=n;i++) cin>>a[i][0]>>a[i][1]; //橫縱座標 cin>>m; //m處聯通 memset(b,0x7f,sizeof(b)); //先將所有的元素賦爲無窮大 for(int i=1;i<=m;i++) { cin>>x>>y; //點x與點y是聯通的 b[x][y]=b[y][x]=sqrt(pow((double)(a[x][0]-a[y][0]),2)+pow((double)(a[x][1]-a[y][1]),2)); //利用鄰接矩陣的對稱性減小一半運算,兩點間距離公式算距離,注意改爲double類型 } for(int k=1;k<=n;k++) //Floyd算法,O(n^3)複雜度 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j&&i!=k&&j!=k&&((b[i][k]+b[k][j])<b[i][j])) b[i][j]=b[i][k]+b[k][j]; //若是第i點和第j點間有個間接點k使得第i個點到第k個點的距離+k個點到第j個點的距離<小於第i個點到第j個點的直接距離,則將最短距離更新 cin>>aa>>bb; //題目要求的第aa個點到第bb個點的矩陣 printf("%.2lf",b[aa][bb]); //直接輸出 return 0; }
完結撒花qaq~