计蒜客 百度地图的实时路况 【cdq+floyd】

来源:互联网 发布:知网和知乎哪个好 编辑:程序博客网 时间:2024/04/27 21:33

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

分析:题目要求所有的dis(x,y,z); x到z不经过y的最短路。考虑暴力做法,枚举每一个点表示不经过它,跑n次floyd。。显然n^4过不去。

我们在求最短路的时候很多i到j的最短路重复的求过了。考虑分治,每次求(l,r)可以用(l,mid)求floyd表示用可能用到了(l,mid)中的点,到(mid+1,r)中找没有经过某点的最短路,直到l==r时就是可以找到所有不经过l的所有点对最短路了。


代码:

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<string>#include<vector>#include<queue>#include<cmath>#include<stack>#include<set>#include<map>#define INF 0x3f3f3f3f3f3f3f3f#define Mn 305#define Mm 2000005#define mod 1000000007#define CLR(a,b) memset((a),(b),sizeof((a)))#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))#define CPY(a,b) memcpy ((a), (b), sizeof((a)))#pragma comment(linker, "/STACK:102400000,102400000")#define ul u<<1#define ur (u<<1)|1using namespace std;typedef long long ll;ll dis[Mn][Mn],now[10][Mn][Mn];ll ans=0;int n;void cdq(int l,int r,int deep) {    if(l==r) {        for(int i=1;i<=n;i++) {            for(int j=1;j<=n;j++) {                if(i==l||j==l) continue;                if(dis[i][j]==INF) ans-=1;                else ans+=dis[i][j];            }        }        return ;    }    int mid=(l+r)>>1;    for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++) now[deep][i][j]=dis[i][j];    for(int k=l;k<=mid;k++) {        for(int i=1;i<=n;i++) {            for(int j=1;j<=n;j++) {                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);            }        }    }    cdq(mid+1,r,deep+1);    for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++) dis[i][j]=now[deep][i][j];    for(int k=mid+1;k<=r;k++) {        for(int i=1;i<=n;i++) {            for(int j=1;j<=n;j++) {                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);            }        }    }    cdq(l,mid,deep+1);}int main() {    int x;    scanf("%d",&n);    for(int i=1;i<=n;i++) {        for(int j=1;j<=n;j++) {            scanf("%d",&x);            if(x==-1) dis[i][j]=INF;            else dis[i][j]=x;        }    }    cdq(1,n,0);    printf("%lld",ans);    return 0;}





0 0