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

来源:互联网 发布:甘肃网络机柜 编辑:程序博客网 时间:2024/05/17 08:28

Description

定义d(u,v,w)为从 u 号点出发,严格不经过 v 号点,最终到达 w 号点的最短路径长度,求1x,y,zn,xy,yzd(x,y,z)

Solution

考虑分治即可,Floyd本身是一个不断利用中转点更新其他点的过程,与其本身的顺序无关,那么每次分治跑一下Floyd就好了

#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int N = 310;const int INF = 0x3f3f3f3f;typedef long long ll;inline char get(void) {  static char buf[100000], *S = buf, *T = buf;  if (S == T) {    T = (S = buf) + fread(buf, 1, 100000, stdin);    if (S == T) return EOF;  }  return *S++;}inline void read(int &x) {  static char c; x = 0; int sgn = 0;  for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;  for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';  if (sgn) x = -x;}int mp[N][N];int n;ll ans;struct Floyd {  int mp[N][N];  Floyd(void) {    memset(mp, 0x3f, sizeof mp);  }  inline int* operator [](const int x) {    return mp[x];  }};Floyd S;inline int Min(int a, int b) {  return a < b ? a : b;}void DivAndConq(int l, int r, Floyd &F) {  if (l == r) {    for (int i = 1; i <= n; i++)      if (i != l)        for (int j = 1; j <= n; j++)          if (j != l) ans += F[i][j] == INF ? -1 : F[i][j];    return;  }  Floyd P = F;  int mid = (l + r) >> 1;  for (int k = l; k <= mid; k++)    for (int i = 1; i <= n; i++)      for (int j = 1; j <= n; j++)        P[i][j] = Min(P[i][j], P[i][k] + P[k][j]);  DivAndConq(mid + 1, r, P);  P = F;  for (int k = mid + 1; k <= r; k++)    for (int i = 1; i <= n; i++)      for (int j = 1; j <= n; j++)        P[i][j] = Min(P[i][j], P[i][k] + P[k][j]);  DivAndConq(l, mid, P);}int main(void) {  freopen("1.in", "r", stdin);  freopen("1.out", "w", stdout);  read(n);  for (int i = 1; i <= n; i++)    for (int j = 1; j <= n; j++) {      read(S[i][j]);      if (S[i][j] == -1) S[i][j] = INF;    }  DivAndConq(1, n, S);  cout << ans << endl;  return 0;}
0 0
原创粉丝点击