二叉樹的序列化,就那幾個框架,枯燥至極
阿新 • • 發佈:2020-11-15
題目連結:P1119
題目大意:
有點複雜,略了,大概就是有Q次詢問,每次詢問在有些道路不能走的情況下,給定的兩個村莊的最短路。
解題思路:
為什麼說是好題?因為明白了不是所有的非負權圖最短路,dijkstra都合適。看完題目,首先想到DJ演算法,但是忽略了複雜度,DJ複雜度mlogn,q次詢問就是qmlogn,大概時1e9+常數,沒錯會T。雖然Floyd是n³,但是因為這個題的特殊(或者說是巧妙),可以把最外層迴圈放在每次詢問裡,這樣總的複雜度大概也是n³。
Floyd思想就是,每次只允許經過k個點時,圖中兩點之間的最短距離是多少,其中
f[i][j] = min(f[i][j], f[i][k]+f[k][j]); 有迪屁的思想。
根據Floyd還可求正權無向圖的最小權值環,以及圖的傳遞閉包。
參考程式碼:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <queue> 6 #include <stack> 7 #include <vector> 8 #include <algorithm> 9 #define N 2010 10 using namespace std;11 const int MAX = 1061109567; // memset(f,0x3f,sizeof(f))後元素的值 12 int f[N][N],t[N]; // 鄰接矩陣存圖 13 14 inline int read() 15 { 16 int x = 0, y = 1; char c = getchar(); 17 while(c < '0' || c > '9') {if(c == '-') y = -1; c = getchar();} 18 while(c >= '0' && c <= '9') x = x*10+c-'0', c = getchar();19 return x*y; 20 } 21 // 初始化 22 void init() 23 { 24 memset(f,0x3f,sizeof(f)); 25 for(int i = 0; i < N; i++) 26 for(int j = 0; j < N; j++) 27 if(i == j) 28 f[i][j] = 0; 29 } 30 31 int main() 32 { 33 init(); 34 int k = 0; 35 int n,m,q; 36 int u,v,wi; 37 int x,y,ti; 38 n = read(); 39 m = read(); 40 for(int i = 0; i < n; i++) 41 t[i] = read(); 42 for(int i = 0; i < m; i++) 43 { 44 u = read(); 45 v = read(); 46 wi = read(); 47 f[u][v] = f[v][u] = wi; // 雙向邊 48 } 49 q = read(); 50 while(q--) 51 { 52 x = read(); 53 y = read(); 54 ti = read(); 55 if(t[x] > ti || t[y] > ti) // 感覺這個判斷放在前面,有些資料是可以很節省時間的 56 { 57 printf("-1\n"); 58 continue; 59 } 60 while(t[k] <= ti && k < n) 61 { 62 for(int i = 0; i < n; i++) 63 for(int j = 0; j < n; j++) 64 f[i][j] = f[j][i] = min(f[i][j],f[i][k]+f[k][j]);// Floyd的核心 65 k++; 66 } 67 if(f[x][y] == MAX) printf("-1\n"); 68 else printf("%d\n",f[x][y]); 69 } 70 return 0; 71 }