【BZOJ 2118】墨墨的等式
http://www.lydsy.com/JudgeOnline/problem.php?id=2118
最短路就是为了找到最小的$x$满足$x=k×a_{min}+d,0≤d<a_{min}$
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N = 500003; int in() { int k = 0, fh = 1; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) if (c == '-') fh = -1; for(; c >= '0' && c <= '9'; c = getchar()) k = (k << 3) + (k << 1) + c - '0'; return k * fh; } ll inll() { ll k = 0; int fh = 1; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) if (c == '-') fh = -1; for(; c >= '0' && c <= '9'; c = getchar()) k = (k << 3) + (k << 1) + c - '0'; return k * fh; } struct node { int nxt, to, w; } E[N * 12]; struct Point { int id; ll dist; Point(int _id = 0, ll _dist = 0) : id(_id), dist(_dist) {} bool operator < (const Point &A) const { return dist > A.dist; } }; ll dist[N], Bmin, Bmax; bool inq[N]; int p, n, a[13], cnt = 0, point[N]; void ins(int u, int v, int w) {E[++cnt] = (node) {point[u], v, w}; point[u] = cnt;} void dijkstra(int s) { for(int i = 1; i < p; ++i) dist[i] = 2500000000000ll; dist[s] = 0; priority_queue <Point> q; q.push(Point(s, 0)); Point u; while (!q.empty()) { u = q.top(); q.pop(); if (inq[u.id]) continue; inq[u.id] = true; for(int i = point[u.id]; i; i = E[i].nxt) if (u.dist + E[i].w < dist[E[i].to]) { dist[E[i].to] = u.dist + E[i].w; q.push(Point(E[i].to, dist[E[i].to])); } } } ll solve(ll x) { ll ret = 0; for(int i = 0; i < p; ++i) if (x >= dist[i]) ret += (x - dist[i]) / p + 1; return ret; } int main() { n = in(); Bmin = inll(); Bmax = inll(); for(int i = 1; i <= n; ++i) a[i] = in(); sort(a + 1, a + n + 1); p = a[1]; for(int i = 0; i < p; ++i) for(int j = 2; j <= n; ++j) ins(i, (i + a[j]) % p, a[j]); dijkstra(0); printf("%lld\n", solve(Bmax) - solve(Bmin - 1)); return 0; }
堆优化dijkstra模板↑
NOI 2017 Bless All