百度地图的实时路况 2016 计蒜之道 复赛

https://nanti.jisuanke.com/t/A1108

way1:

应该很多同学的做法都是对于每次y,每次x,dijkstra+堆优化

n^2 * nlogn

其实log(300)很小。。。

way2:

题解方法真心优秀!!!

cdq分治

有助于理解floyd:每次加入一个可以使用的点,加n次,顺序可以调整

本题:对于每个y,仅仅是y点不能使用

每次计算1/2,cdq剩下的1/2(left,right分别来一次),直到只剩下一个数,这个点不用于求最短路。所有点都有且仅有一次出现“只剩下该点”的情况。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 #include <iostream>
 8 using namespace std;
 9 #define ll long long
10 
11 const double eps=1e-8;
12 const int inf=1e9;
13 const ll mod=1e9+7;
14 const int maxn=3e2+10;
15 
16 int dist[maxn][maxn];
17 ll sum;
18 int n;
19 
20 void cdq(int l,int r)
21 {
22     int i,j;
23     if (l==r)
24     {
25         for (i=1;i<=n;i++)
26             for (j=1;j<=n;j++)
27                 if (i!=l && j!=l)
28                     sum+=dist[i][j]==inf?-1:dist[i][j];
29         return;
30     }
31     int m=(l+r)>>1,k,temp[maxn][maxn];
32     memcpy(temp,dist,sizeof(dist));
33     for (k=l;k<=m;k++)
34         for (i=1;i<=n;i++)
35             for (j=1;j<=n;j++)
36                 if (dist[i][j]>dist[i][k]+dist[k][j])
37                     dist[i][j]=dist[i][k]+dist[k][j];
38     cdq(m+1,r);
39 
40     memcpy(dist,temp,sizeof(temp));
41     for (k=m+1;k<=r;k++)
42         for (i=1;i<=n;i++)
43             for (j=1;j<=n;j++)
44                 if (dist[i][j]>dist[i][k]+dist[k][j])
45                     dist[i][j]=dist[i][k]+dist[k][j];
46     cdq(l,m);
47 }
48 
49 int main()
50 {
51     int i,j;
52     scanf("%d",&n);
53     for (i=1;i<=n;i++)
54         for (j=1;j<=n;j++)
55         {
56             scanf("%d",&dist[i][j]);
57             if (dist[i][j]==-1)
58                 dist[i][j]=inf;
59         }
60     cdq(1,n);
61     printf("%lld",sum);
62     return 0;
63 }