【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模板↑

posted @ 2016-08-18 09:47  abclzr  阅读(195)  评论(0编辑  收藏  举报