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
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;
|
|
} |