洛谷P2384 最短路,積化加
阿新 • • 發佈:2020-08-13
題意:給定 n 個點的帶權有向圖,求從 1 到 n 的路徑中邊權之積最小,最終答案對9987取模。
進行最短路鬆弛時,取對數,積化加,存一下前驅點和原邊長即可
#include <cstdio> #include <cmath> #include <iostream> #include <queue> #include <algorithm> #include <string.h> using namespace std; const int mo = 9987; const int N = 1010; const int M = 1000010; int n, m, l = 0; int last[N] = {0}, r[N][2]; double dis[N]; bool vis[N] = {false}; int pre[M], len[M], other[M]; struct rec { int x; double dis; bool operator < (const rec &a) const { return(a.dis < dis); } }; inline void read(int &x) { x = 0; bool flag = false; char ch; while (ch = getchar(), ch < '!'); if (ch == '-') flag = true, ch = getchar(); while (x = x * 10 + ch - '0', ch = getchar(), ch > '!'); if (flag) x = -x; } void connect(int x, int y, int z) { l++; pre[l] = last[x]; last[x] = l; other[l] = y; len[l] = z; } void dijkstra() { priority_queue<rec> que; for (int i = 1; i <= n; i++) dis[i] = 0x3f3f3f3f; dis[1] = 0; que.push(rec{1, 0}); // while (!que.empty()) { rec cur = que.top(); que.pop(); if (vis[cur.x]) continue; vis[cur.x] = true; // int p, q; q = last[cur.x]; while (q) { p = other[q]; if (dis[p] > dis[cur.x] + log(len[q])) { dis[p] = dis[cur.x] + log(len[q]); que.push(rec{p, dis[p]}); r[p][0] = cur.x; r[p][1] = len[q]; } q = pre[q]; } } } int main() { read(n); read(m); for (int i = 1; i <= m; i++) { int x, y, z; read(x); read(y); read(z); connect(x, y, z); } dijkstra(); int cur = n; int ans = 1; while (cur != 1) { ans = (ans * r[cur][1]) % mo; cur = r[cur][0]; } printf("%d\n", ans); return 0; }