LuoguP2384 最短路 题解

堆优化+\(Dijkstra\)居然跑过去了?


其实和普通的最短路没什么两样,就是把dis[y]=dis[x]+z变成dis[y]=(dis[x]*z+mod)%mod就行了。

但你会发现交上去只有\(\color{LimeGreen} \text{90}\)分。

为什么?

仔细看题:

所求路径的边权之积!!!

有可能某条路径刚好是\(9987\)(模数),然后你的最小乘积路径就死打不动地变成\(0\)了!

所以,需要将\(mod\)\(0\)的某个\(dis\)变成\(1\),就像这样:dis[y] = max((dis[x] * z + mod) % mod, 1ll);

然后毫无压力地跑过去了,\(45ms\)左右的时间。可以说加强数据好像没什么用吗


\(AC\)代码:

#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;

const long long mod = 9987;
long long n, m, u, v, w, dis[1007], vis[1007], h[1000007], cnt;
priority_queue<pair<long long, long long> > q;
struct edge {
	long long v, to, nxt;
}e[1000007];

inline void a_e(long long u, long long v, long long w) {
	e[++cnt] = (edge){w, v, h[u]}; h[u] = cnt;
//	e[++cnt] = (edge){w, u, h[v]}; h[v] = cnt;
}
inline void dj() {
	for(long long i = 1; i <= n; ++i)	dis[i] = (long long)(pow(2, 31) - 1);
	dis[1] = 1;
	q.push(make_pair(0, 1));
	while(!q.empty()) {
		long long x = q.top().second;
		q.pop();
		if(vis[x])	continue;
		vis[x] = 1;
		for(long long i = h[x]; i; i = e[i].nxt) {
			long long y = e[i].to, z = e[i].v;
			if(dis[y] > dis[x] * z) {
				dis[y] = max((dis[x] * z + mod) % mod, 1ll);
				q.push(make_pair(-dis[y], y));
			}
		}
	}
}
inline long long read() {
	long long f = 1, x = 0;
	char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-')	f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x * f;
}

int main() {
	n = read(), m = read();
	for(long long i = 1; i <= m; ++i) {
		u = read(), v = read(), w = read();
		a_e(u, v, w);
	}
	dj();
	printf("%lld", dis[n]);
	return 0;
}
posted @ 2021-12-23 21:00  Eason_AC  阅读(27)  评论(0)    收藏  举报