P2384 最短路

新博客地址:https://gyrojeff.top,欢迎访问! 本文为博客自动同步文章,为了更好的阅读体验,建议您移步至我的博客👇

本文标题:P2384 最短路

文章作者:gyro永不抽风

发布时间:2020年09月18日 - 17:09

最后更新:2020年09月19日 - 19:09

原始链接:http://hexo.gyrojeff.moe/2020/09/18/P2384-%E6%9C%80%E7%9F%AD%E8%B7%AF/

许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 转载请保留原文链接及作者!

题目

(直接从洛谷网站上复制的div)

题目背景

狗哥做烂了最短路,突然机智的考了 Bosh 一道,没想到把 Bosh 考住了...你能帮 Bosh 解决吗?

题目描述

给定 nn 个点的带权有向图,求从 11nn 的路径中边权之积最小的简单路径。

输入格式

第一行读入两个整数 nnmm,表示共 nn 个点 mm 条边。 接下来 mm 行,每行三个正整数 xxyyzz,表示点 xx 到点 yy 有一条边权为z的边。

输出格式

输出仅包括一行,记为所求路径的边权之积,由于答案可能很大,因此狗哥仁慈地让你输出它模 99879987 的余数即可。

废话当然是一个数了w

//谢fyszzhouzj指正w

输入输出样例

输入 #1
3 3
1 2 3 
2 3 3 
1 3 10
输出 #1
9

说明/提示

对于 20%20\% 的数据,n10n\leq 10

对于 100%100\% 的数据,n103n\leq 10^3m106m\leq 10^6。边权不超过 10410^4

题解

这道题注意点:乘积。一般有两种解决方式:

  • 对数
  • 记录路径

对数的话涉及到$\log$然后再还原到int可能会出现问题(反正我是失败了,我,菜),所以这里介绍第二种方法:直接记录路径,下面是具体分析。

记录路径

我们可以发现,在dijkstravoid里更新判断的if里面更新时,更新的情况一定是优于原来的的。那么就在更新时记录前继呗。然后由于我们是邻接表存图,所以再记录一下边权就完事了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <cstdio>
#include <queue>
#include <iostream>
#include <cmath>
#define int long long

using namespace std;

const int maxn = 1000005;

int head[maxn];
int ecnt = 2, n, m;
double dis[maxn];
int pre[maxn];
int pre_weight[maxn];
bool vis[maxn];

struct edge {
int to, next, w;
} g[maxn << 1];
void add_edge(int u, int v, int w) {
g[ecnt] = (edge) { v, head[u], w };
head[u] = ecnt ++;
}

struct node {
double dis, pos;
friend bool operator < (const node &a, const node &b) {
return a.dis > b.dis;
}
};
priority_queue<node> q;

void dijkstra() {
for (int i = 1; i <= n; i ++) dis[i] = 8e18;
dis[1] = 0; q.push((node) { 0, 1 });
while (!q.empty()) {
int u = q.top().pos; q.pop();
if (vis[u]) continue;
vis[u] = true;
for (int e = head[u]; e != 0; e = g[e].next) {
int v = g[e].to;
if (dis[v] > dis[u] + log2(g[e].w)) {
dis[v] = dis[u] + log2(g[e].w);
q.push((node) { dis[v], v });
pre[v] = u;
pre_weight[v] = g[e].w;
}
}
}
}

signed main() {
cin >> n >> m;
for (int i = 1; i <= m; i ++) {
int x, y, z; cin >> x >> y >> z;
add_edge(x, y, z);
if (z == 0) {
cout << 0 << endl;
return 0;
}
}
dijkstra();
int i = n;
int ans = 1;
while (pre[i] != 0) {
ans = ans * pre_weight[i];
ans = ans % 9987;
i = pre[i];
}
cout << ans << endl;
}
posted @ 2020-09-19 00:11  gyro永不抽风  阅读(120)  评论(0编辑  收藏  举报