P1119 灾后重建

题目链接: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 }

 

posted @ 2020-11-16 15:19  不敢说的梦  阅读(65)  评论(0)    收藏  举报