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

来源:互联网 发布:模拟教学软件 编辑:程序博客网 时间:2024/05/17 06:10

题目链接:点这里!!!!


题意:中文题


官方题解:

枚举 d(x , y , z)d(x,y,z) 中的 yy,把 yy 从这个图中删去,再求这时的全源最短路即可,使用 Floyd 算法来做上述过程。Floyd 算法可以是一个增量的过程,虽然第一维一般都是从 11 枚举到 kk 但是这个枚举的顺序并不影响最后的结果。所以如果可以预处理出对于每个点 yy 只剩 yy 没有在 Floyd 的第一维枚举到的矩阵,这个矩阵的值就是不经过 yy 点的全源最短路。

所以使用分治,每一次把点集拆成两半,先用前一半的点在 Floyd 算法中滚,再递归后一半点。然后回溯,用后一半的点在 Floyd 算法里滚,递归前一半的点。这样每个只有一个点的状态得到的就是只有这个点没有在 Floyd 算法里滚的矩阵。

时间复杂度为 O(n^3 \log n)O(n3logn)

分治的是k.

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<sstream>#include<algorithm>#include<vector>#include<bitset>#include<set>#include<queue>#include<stack>#include<map>#include<cstdlib>#include<cmath>#define LL long long#define pb push_back#define pa pair<int,int>#define clr(a,b) memset(a,b,sizeof(a))#define lson lr<<1,l,mid#define rson lr<<1|1,mid+1,r#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)#define key_value ch[ch[root][1]][0]#pragma comment(linker, "/STACK:102400000000,102400000000")const LL  MOD = 1000000007;const int N = 300+15;const int maxn = 8e3+15;const int letter = 130;const LL INF = 1e7;const double pi=acos(-1.0);const double eps=1e-10;using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int n;LL dp[10][N][N],ans=0;void cdq(int L,int R,int dep){    if(L==R){        for(int i=1;i<=n;i++){            if(i==L) continue;            for(int j=1;j<=n;j++){                if(j==L) continue;                ans+=(dp[dep-1][i][j]>=INF?-1:dp[dep-1][i][j]);            }        }        return;    }    int mid=(L+R)>>1;    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++)        dp[dep][i][j]=dp[dep-1][i][j];    for(int k=L;k<=mid;k++){        for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++){            dp[dep][i][j]=min(dp[dep][i][j],dp[dep][i][k]+dp[dep][k][j]);        }    }    cdq(mid+1,R,dep+1);    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++){        dp[dep][i][j]=dp[dep-1][i][j];    }    for(int k=mid+1;k<=R;k++){        for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++){            dp[dep][i][j]=min(dp[dep][i][j],dp[dep][i][k]+dp[dep][k][j]);        }    }    cdq(L,mid,dep+1);}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++){        scanf("%lld",&dp[0][i][j]);        if(dp[0][i][j]==-1)dp[0][i][j]=INF;    }    cdq(1,n,1);    printf("%lld\n",ans);    return 0;}




0 0
原创粉丝点击