最短路板子第一彈·Dijkstra基礎
阿新 • • 發佈:2018-12-16
1. Dijkstra
無圖警告
1.1 思路
Dijkstra的來歷不必多講,但是需要知道的,是Dijkstra是一種基於“貪心“的求“單源最短路”演算法,和最小生成樹中的Prim是類似的。(如果你不知道什麼是單源最短路,建議百度一下再來)
粗略來講,Dijkstra的做法就是:
以起始點為中心向外層層擴充套件,直到擴充套件到終點為止 ——百度百科
既然是這樣,我們的鬆弛操作就該登場了
1.2 最短路的靈魂——鬆弛
何謂鬆弛?簡單講,一根變成兩根,它不就鬆了嗎?也就是說,把一條邊用幾條比它更短的邊來替代,就是鬆弛了。
於是就出現了諸如這樣的程式碼塊:
if(d[i] > d[j] + w[i, j])
{
d[i] = d[j] + w[i, j];
}
這裡的代表點到出發點的最短距離,即答案。
這裡的代表點到點的已經存在的路徑的長度,就是讀進來的那個,先用鄰接矩陣存著。
Ps:如果你剛剛學,建議在這裡停下來用至少5分鐘“用心”想想為什麼,可以畫畫圖,查查相關資料(比如別人的Blog)。真正的學懂,一定是理解,能夠自己推出來,而不是單純的記憶。
1.3 完整程式碼+註釋
相信理解過以上兩點的基本上就懂了,所以就不多解釋了。(逃
不過啊,前方大量註釋預警:(程式碼就忍著點看吧qwq)
#include<bits/stdc++.h> using namespace std; typedef double dd; typedef long long ll; #define fora(i, j, k) for(int i = j; i <= k; ++i) #define forb(i, j, k) for(int i = j; i >= k; --i) #define Set(a, b) memset(a, b, sizeof(a)) inline ll lax(ll x, ll y) {return x > y ? x : y;} inline ll lin(ll x, ll y) {return x < y ? x : y;} inline ll read() { char c = getchar(); ll s = 0; int tip = 1; for(; c < '0' || c > '9'; c = getchar()) if(c == '-') tip = -1; for(; c >= '0' && c <= '9'; c = getchar()) s = s * 10 + c - '0'; return s * tip; } //從這裡開始看就好,上面都是板子。 const int maxn = 10000 + 10; const int maxm = 500000 + 10; const int INf = 2147483647; int i, j, k, m, n, mind, t; int a[maxm], b[maxm], c[maxm], u[maxn], v[maxm], d[maxn]; bool book[maxn]; void file() { freopen("dijkstra.in", "r", stdin); freopen("dijkstra.out", "w", stdout); } void init() { n = read(), m = read(), k = read(); fora(i, 1, m) { a[i] = read(), b[i] = read(), c[i] = read(); v[i] = u[a[i]], u[a[i]] = i; } fora(i, 1, n) if(i != k) d[i] = INf; } void work() { fora(i, 1, n) { mind = INf, t = 0; fora(j, 1, n) if(book[j] == 0 && d[j] < mind) mind = d[j], t = j; book[t] ^= 1; int j = u[t]; for(; j != 0; j = v[j]) if(book[b[j]] == 0 && d[b[j]] > d[t] + c[j]) d[b[j]] = d[t] + c[j]; } } void write() { fora(i, 1, n) printf("%d ", d[i]); cout << endl; } int main() { // file(); init(); //初始化部分 work(); //主要操作部分 write(); //輸出部分 return 0; //沒了 }
看完以後就關上它,自己寫一遍,交到各大評測網站上吧! 傳送門來著的