#include using namespace std; const int N = 10010, M = N << 1, K = 110; // 链式前向星 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++; } // 入队列的结构体 struct Node { int id; // 节点号 int r; // %k的余数 }; int dis[N][K]; // 最短路径 int n, m, k; // n个节点,m条边,时间是k的整数倍,即 %k=0 bool bfs(int mid) { memset(dis, -1, sizeof dis); queue q; dis[n][0] = mid * k; q.push({n, 0}); while (q.size()) { int u = q.front().id; int r = q.front().r; q.pop(); if (dis[u][r] == 0) continue; // 反着走,距离为0,就不需要继续走了,剪枝 for (int i = h[u]; ~i; i = ne[i]) { int v = e[i]; // 前序节点 int p = (r - 1 + k) % k; // 前序节点合法状态 if (~dis[v][p]) continue; // 如果前序点的合法状态不等于-1,表示已经被宽搜走过了,根据宽搜的理论,就是已经取得了最短距离,不需要再走 if (dis[u][r] - 1 < w[i]) continue; // 现在的最短距离是dis[u][r],那么前序的距离应该是dis[u][r]-1,那么,如果dis[u][r]-1> n >> m >> k; while (m--) { int a, b, c; cin >> a >> b >> c; add(b, a, c); } int l = 0, r = (1e6 + 1e4) / k, ans = -1; while (l < r) { int mid = l + r >> 1; if (bfs(mid)) { ans = mid * k; r = mid; } else l = mid + 1; } cout << ans << endl; return 0; }