POJ-2387 Til the Cows Come Home
阿新 • • 發佈:2020-09-03
hyh大佬很熱愛學習,他打算偷偷跑回學校學習,為了多學習他希望可以找最快的路線回到學校。
廣州市裡有N個(2 <= N <= 1000)個地鐵站,編號分別為1..N。zzj家在1號地鐵站旁邊,五山站是N號地鐵站。地鐵站之間共有M (1 <= M <= 2000)條雙向路徑。
hyh現在在1號地鐵站,他希望知道到學校最短要多長時間。可以保證hyh能到達學校。忽略hyh在換乘地鐵時需要的等待時間
Sample Input 5 5 1 2 20 2 3 30 3 4 20 4 5 20 1 5 100 Sample Output 90
Dijkstra演算法思想:主要特點是從起始點開始,採用 貪心演算法的策略,每次遍歷到始點距離最近且未訪問過的頂點的鄰接節點,直到擴充套件到終點為止。 時間複雜度O(n^2),程式碼如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxx = 1005; int adj[maxx][maxx]; // 鄰接表來儲存圖的資訊 bool found[maxx]; //標記是否訪問過該結點 int t, n; const int inf = 1 << 29; //記住不要將最大值設成101等,雖然說題目給的邊的大小是1 ~ 100 但是輸入資料有坑void init() { // 初始化 for (int i = 1; i <= n ; ++i) { for (int j = 1; j <= n; ++j) { adj[i][j] = inf; } } memset(found, false, n + 1); } void dijkstra() { int dis[n + 1]; for (int i = 1; i <= n; ++i) { dis[i] = adj[n][i]; // 首先對distance陣列進行初始化 我選擇的是從結點n到結點1// 也可以選擇從結點1到結點n } found[n] = true; for (int i = 1; i <= n; ++i) { int minv = 0, mind = inf; //找到在未被訪問的結點之中的最小的結點 for (int j = 1; j <= n; ++j) { if (found[j]) continue; if (dis[j] < mind) { minv = j; mind = dis[j]; } } for (int j = 1; j <= n; ++j) { if (adj[minv][j] != inf) { dis[j] = min(dis[j], adj[minv][j] + dis[minv]); // 對dis進行更新 } } found[minv] = true; } printf("%d\n", dis[1]); } int main() { scanf("%d%d", &t, &n); init(); for (int i = 0; i < t; ++i) { int from, to, edge; scanf("%d%d%d", &from, &to, &edge); adj[from][to] = adj[to][from] = min(adj[from][to], edge); // 去重邊 } dijkstra(); return 0; }
Floyd演算法思想:(時間複雜度O(N^3),在此題中會超時,寫出來只是供大家學習一下)
1,從任意一條單邊路徑開始。所有兩點之間的距離是邊的權,如果兩點之間沒有邊相連,則權為無窮大。 2,對於每一對頂點 u 和 v,看看是否存在一個頂點 w 使得從 u 到 w 再到 v 比已知的路徑更短。如果是更新它。#include <iostream> #include <vector> #include <algorithm> #include <cstdio> typedef long long ll; typedef unsigned long long ull; using namespace std; int t, n; const int maxx = 1005; int gra[maxx][maxx], path[maxx][maxx]; const int inf = 1 << 29; void floyd() { vector<vector<int> > A(n + 1, vector<int>(n + 1)); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { A[i][j] = gra[i][j]; path[i][j] = -1; } } for (int v = 1; v <= n; ++v) { for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { if (A[i][j] > A[i][v] + A[v][j]) { A[i][j] = A[i][v] + A[v][j]; path[i][j] = v; } } } } } int printPath(int v, int w) { if (-1 == path[v][w]) { return gra[v][w]; } int mid = path[v][w]; return printPath(v, mid) + printPath(mid, w); } int main() { scanf("%d%d", &t, &n); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { if (i != j) gra[i][j] = inf; } } for (int i = 0; i < t; ++i) { int from, to, edge; scanf("%d%d%d", &from, &to, &edge); gra[from][to] = gra[to][from] = min(gra[from][to], edge); } floyd(); printf("%d\n", printPath(n, 1)); return 0; }
相比較可得知Dijkstra演算法更優於Floyd演算法,但是,Dijkstra演算法不能處理負權邊而Floyd可以,一般我們可以觀察題目給出的資料大小來選擇我們解題的演算法。