BZOJ4070 [Apio2015]雅加达的摩天楼 【分块 + 最短路】
2018-06-15 08:18
363 查看
题目链接
题解
考虑暴力建图,将每个\(B_i\)向其能到的点连边,复杂度\(O(\sum \frac{n}{p_i})\),当\(p\)比较小时不适用
考虑优化建图,每个\(doge\)能移动的点实际上是一组模\(p\)同余的点,那么只要对每个\(p\)建\(n\)个点,然后内部距离为\(p\)的点连边,然后每个点向原来的点连边,如果某个点有步长为\(p\)的\(doge\),则原点向该点连边,这样子每一层点数和边数都是\(O(n)\)的,复杂度是\(O(pn)\),当\(p\)较小时使用
如此可以得出最终算法,分块处理
对于\(p\)较小的点优化建图,\(p\)较大的点暴力建图
跑最短路即可
如果是\(dijsktra\),复杂度\(O(n\sqrt{n}log(n\sqrt{n}))\)
但据说这里\(spfa\)快?
#include<algorithm> #include<iostream> #include<cstring> #include<queue> #include<cstdio> #include<cmath> #include<map> #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt) #define REP(i,n) for (int i = 1; i <= (n); i++) #define mp(a,b) make_pair<int,int>(a,b) #define cls(s) memset(s,0,sizeof(s)) #define cp pair<int,int> #define LL long long int using namespace std; const int maxn = 4000005,maxm = 15000005,INF = 1000000000; inline int read(){ int out = 0,flag = 1; char c = getchar(); while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();} while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();} return out * flag; } int h[maxn],ne = 1; struct EDGE{int to,nxt,w;}ed[maxm]; inline void build(int u,int v,int w){ ed[++ne] = (EDGE){v,h[u],w}; h[u] = ne; } int n,m,B,d[maxn],inq[maxn],S,T; queue<int> q; void spfa(){ int E = B * n + n; for (int i = 1; i <= E; i++) d[i] = INF; d[S] = 0; q.push(S); int u; while (!q.empty()){ u = q.front(); q.pop(); inq[u] = false; Redge(u) if (d[to = ed[k].to] > d[u] + ed[k].w){ d[to] = d[u] + ed[k].w; if (!inq[to]) q.push(to),inq[to] = true; } } } int main(){ n = read(); m = read(); B = min((int)sqrt(n),100); for (int i = 1; i <= B; i++){ for (int j = 1; j <= i; j++){ for (int u = j; u + i <= n; u += i){ build(i * n + u,i * n + u + i,1); build(i * n + u + i,i * n + u,1); } } for (int j = 1; j <= n; j++) build(i * n + j,j,0); } int x,p; for (int t = 1; t <= m; t++){ x = read() + 1; p = read(); if (t == 1) S = x; if (t == 2) T = x; if (p > B){ for (int i = p,j = 1; x - i > 0; i += p,j++) build(x,x - i,j); for (int i = p,j = 1; x + i <= n; i += p,j++) build(x,x + i,j); } else build(x,p * n + x,0); } spfa(); if (d[T] == INF) puts("-1"); else printf("%d\n",d[T]); return 0; }
相关文章推荐
- bzoj 4070: [Apio2015]雅加达的摩天楼 最短路+分块
- 【bzoj4070】[Apio2015]雅加达的摩天楼 分块+最短路
- 【bzoj4070】【APIO2015】【雅加达的摩天楼】【最短路】
- BZOJ 4070:[APIO2015]雅加达的摩天楼 最短路
- BZOJ 4070 [Apio2015]雅加达的摩天楼 ——分块 SPFA
- 【bzoj4070】[Apio2015]雅加达的摩天楼 set+堆优化Dijkstra
- 【BZOJ 4070】【APIO 2015】雅加达的摩天楼
- 【BZOJ 4070】 [Apio2015]雅加达的摩天楼
- UOJ 111 & BZOJ 4070 [Apio2015]雅加达的摩天楼
- [SPFA 分块建图] BZOJ 4070 [Apio2015]雅加达的摩天楼
- bzoj 4070: [Apio2015]雅加达的摩天楼【spfa】
- 【BZOJ4070】[Apio2015]雅加达的摩天楼 set+最短路
- bzoj4070【APIO2015】雅加达的摩天楼
- bzoj 4070: [Apio2015]雅加达的摩天楼
- 4070: [Apio2015]雅加达的摩天楼
- 4070: [Apio2015]雅加达的摩天楼
- BZOJ4070: [Apio2015]雅加达的摩天楼
- APIO2015 Bali Sculptures UOJ111 BZOJ4070
- [APIO2015]雅加达的摩天楼
- BZOJ4070: [Apio2015]雅加达的摩天楼