2016计蒜之道复赛 百度地图的实时路况 floyd+cdq分治

链接:https://nanti.jisuanke.com/t/11217

奉上官方题解:

枚举 d(x , y , z) 中的 y,把 y 从这个图中删去,再求这时的全源最短路即可,使用 Floyd 算法来做上述过程

Floyd 算法可以是一个增量的过程,虽然第一维一般都是从 1枚举到 k但是这个枚举的顺序并不影响最后的结果。

所以如果可以预处理出对于每个点 y,只剩 y 没有在 Floyd 的第一维枚举到的矩阵,这个矩阵的值就是不经过 y 点的全源最短路。

所以使用分治,每一次把点集拆成两半,先用前一半的点在 Floyd 算法中滚,再递归后一半点。

然后回溯,用后一半的点在 Floyd 算法里滚,递归前一半的点。这样每个只有一个点的状态得到的就是只有这个点没有在 Floyd 算法里滚的矩阵。

时间复杂度为 O(n^3​​logn)。

吐槽:在写这个题以前,cdq分治只写过三维偏序模板题,整体二分的题写的很少,以后要应该多写一些

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <utility>
using namespace std;
typedef long long LL;
const int N=305;
const int INF=0x3f3f3f3f;
int dp[25][N][N],n,mp[N][N];
LL ret;
void cpydp(int dep){
  for(int i=1;i<=n;++i)
    for(int j=1;j<=n;++j)
      dp[dep][i][j]=dp[dep-1][i][j];
}
void update(int dep,int l,int r){
  for(int k=l;k<=r;++k)
    for(int i=1;i<=n;++i)
      for(int j=1;j<=n;++j)
        if(dp[dep][i][j]>dp[dep][i][k]+dp[dep][k][j])
           dp[dep][i][j]=dp[dep][i][k]+dp[dep][k][j];
}
void cdq(int dep,int l,int r){
  if(l==r){
    for(int i=1;i<=n;++i)
      for(int j=1;j<=n;++j){
        if(i==l||j==l)continue;
        if(dp[dep][i][j]==INF)dp[dep][i][j]=-1;
        ret+=1ll*dp[dep][i][j];
      }
    return;
  }
  int m=l+r>>1;
  cpydp(dep+1),update(dep+1,m+1,r);
  cdq(dep+1,l,m);
  cpydp(dep+1),update(dep+1,l,m);
  cdq(dep+1,m+1,r);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
      for(int j=1;j<=n;++j){
        scanf("%d",&dp[0][i][j]);
        if(dp[0][i][j]==-1)dp[0][i][j]=INF;
      }  
    cdq(0,1,n);
    cout<<ret<<endl;
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/shuguangzw/p/5643071.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值