标签:code char ext floyed answer 代码 实时 oid algorithm
https://nanti.jisuanke.com/t/11217
题意:d(u,v,w):从u到w,严格不经过v的路径长度,计算每个d(u,v,w),求和,n 300
分析:
floyed:去掉一个点直接最短路,复杂度$n^4$
优化:去掉一个点,重新做一遍floyed,太浪费了,发现去掉的两个点,除了这两个点不同,其他的中间点都一样。
于是,于是考虑solve(l,r)为l-r的点去掉的floyed矩阵。 二分mid,solve(l,mid),此时先用mid+1~r作为中间点更新了矩阵。然后递归下去处理solve(l,mid),当l=r说明当前的矩阵是去掉了l这个点的矩阵,然后就统计答案。 复杂度$n^3logn$
CDQ分治。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 14 inline int read() { 15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; 16 for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘;return x*f; 17 } 18 19 const int N = 305; 20 const int INF = 1e9; 21 int dis[25][N][N]; 22 int n; 23 LL Answer; 24 25 void update(int dep,int L,int R) { 26 for (int i=1; i<=n; ++i) 27 for (int j=1; j<=n; ++j) 28 dis[dep][i][j] = dis[dep - 1][i][j]; 29 for (int k=L; k<=R; ++k) 30 for (int i=1; i<=n; ++i) 31 for (int j=1; j<=n; ++j) 32 dis[dep][i][j] = min(dis[dep][i][j], dis[dep][i][k] + dis[dep][k][j]); 33 } 34 35 void CDQ(int dep,int L,int R) { 36 if (L > R) return ; 37 if (L == R) { 38 for (int i=1; i<=n; ++i) 39 for (int j=1; j<=n; ++j) 40 if (i != L && j != L) Answer += dis[dep][i][j] == INF ? -1 : dis[dep][i][j]; 41 return ; 42 } 43 int mid = (L + R) >> 1; 44 update(dep + 1, mid + 1, R); CDQ(dep + 1, L, mid); 45 update(dep + 1, L, mid); CDQ(dep + 1, mid + 1, R); 46 } 47 int main() { 48 n = read(); 49 for (int i=1; i<=n; ++i) { 50 for (int j=1; j<=n; ++j) { 51 dis[0][i][j] = read(); 52 if (dis[0][i][j] == -1) dis[0][i][j] = INF; 53 } 54 } 55 CDQ(0, 1, n); 56 cout << Answer; 57 return 0; 58 }
标签:code char ext floyed answer 代码 实时 oid algorithm
原文地址:https://www.cnblogs.com/mjtcn/p/9609403.html