You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
2.4 KiB

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int N = 2e6 + 5, M = N << 1; // 1e4的顶点 * 1e2的分层
// first:起点距离目标点的权重i/ / second:目标点编号
int dis[N];
// 判断是否以某个顶点作为出发点进行松弛
bool st[N];
// m条边
// k个的整数倍
int n, m, k;
// 链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
// 最短路搜索
void dijkstra(int s) {
// 优先队列
priority_queue<PII> q; // n个顶点
memset(dis, INF, sizeof dis);
// 起点距离自己为0
dis[s] = 0;
q.push({0, s});
while (q.size()) {
int u = q.top().second;
q.pop();
// 该点已经被作为起点出发了
if (st[u]) continue;
// 标记此点已经被作为起点使用过
st[u] = 1;
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i]; // 获取当前顶点的目标点
int t = dis[u] + 1; // 到达下一个节点的时间
if (t < w[i]) t += ((w[i] - dis[u] + k - 1) / k) * k;
// https://www.luogu.com.cn/problem/solution/P9751
// while (t < w[i]) t += k;
// w[i]:最早开放时间
// 松弛
if (dis[v] > t) {
dis[v] = t;
// 保证每次筛选出来的都是离起点最近的点
q.push({-dis[v], v});
}
}
}
}
// 计算给定的点在新层中的索引
int get(int layer, int x) {
return layer * n + x;
}
int main() {
memset(h, -1, sizeof h); // 初始化链式前向星
cin >> n >> m >> k; // 读入m条边的信息
while (m--) {
// a为起始点//b为终点
// c是最早开放时间
int a, b, c;
cin >> a >> b >> c;
// 存入分层图
// get(i, a) : 当前层点索引
// get((i + 1) % k, b):下一层K步后所能到达的点
// 当前层和第i+1层建图
for (int i = 0; i < k; i++) add(get(i, a), get((i + 1) % k, b), c);
}
// 调用迪克斯特拉
dijkstra(1);
// 没有找到合法路径
if (dis[n] == INF)
cout << -1 << endl;
else
cout << dis[n] << endl;
return 0;
}