[分治 floyed] 2016 计蒜之道 复赛 百度地图的实时路况

来源:互联网 发布:淘宝保健品许可证图片 编辑:程序博客网 时间:2024/04/28 22:06
使用分治,考虑Floyd算法本来就是一个增量的过程。
记solve(l,r)表示加入除了l到r之间的点的APSP
然后分治
时间复杂度O(n^3logn)

#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#define cl(x) memset(x,0,sizeof(x))using namespace std;typedef long long ll;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }  return *p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=305;const int INF=1e9;int n,w[N][N];ll Ans;inline void Solve(int l,int r,int dis[N][N]){  if (l==r){    for (int i=1;i<=n;i++)      for (int j=1;j<=n;j++)if (i!=j && i!=l && j!=l)  Ans+=dis[i][j]>=INF?-1:dis[i][j];    return;  }  int mid=(l+r)>>1;  int tmp[N][N];  for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) tmp[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++)tmp[i][j]=min(tmp[i][j],tmp[i][k]+tmp[k][j]);  Solve(mid+1,r,tmp);  for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) tmp[i][j]=dis[i][j];   for (int k=mid+1;k<=r;k++)    for (int i=1;i<=n;i++)      for (int j=1;j<=n;j++)tmp[i][j]=min(tmp[i][j],tmp[i][k]+tmp[k][j]);  Solve(l,mid,tmp);}int main(){  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n);  for (int i=1;i<=n;i++)    for (int j=1;j<=n;j++)      read(w[i][j]),w[i][j]=w[i][j]==-1?INF:w[i][j];  int tem[N][N];  for (int i=1;i<=n;i++)    for (int j=1;j<=n;j++)      tem[i][j]=w[i][j];  Solve(1,n,tem);  printf("%lld\n",Ans);  return 0;}


0 0