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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| #include <bits/stdc++.h>
#define int int64_t
const int kMaxN = 2e3 + 5, kMaxM = 2e4 + 5, kMod = 998244353;
int n, m, k; int u[kMaxM], v[kMaxM], w[kMaxM]; int dis1[kMaxN][kMaxN * 4], dis2[kMaxN][kMaxN * 4]; int a[2][kMaxM], b[2][kMaxM]; std::vector<std::pair<int, int>> G[kMaxN];
void dijkstra(int s, int t, int dis[kMaxN][kMaxN * 4]) { for (int i = 1; i <= n; ++i) for (int j = 0; j <= t; ++j) dis[i][j] = 1e18; dis[s][0] = 0; for (int c = 0; c < t; ++c) { for (int i = 1; i <= n; ++i) { for (auto p : G[i]) { int j = p.first, w = p.second; dis[j][c + 1] = std::min(dis[j][c + 1], dis[i][c] + w); } } } }
std::pair<int, int> get(int k1, int b1, int k2, int b2) { k1 -= k2, b1 -= b2; b1 = -b1; if (k1 == 0) return b1 <= 0 ? std::pair<int, int>{0, 1e18} : std::pair<int, int>{1e18, 0}; if (k1 > 0) return {std::max<int>(0, (b1 + k1 - 1) / k1), 1e18}; else return {0, (-b1) / (-k1)}; }
void dickdreamer() { std::cin >> n >> m >> k; for (int i = 1; i <= n; ++i) G[i].clear(); for (int i = 1; i <= m; ++i) { std::cin >> u[i] >> v[i] >> w[i]; G[u[i]].emplace_back(v[i], w[i]), G[v[i]].emplace_back(u[i], w[i]); } dijkstra(1, std::min(k, 4 * n), dis1), dijkstra(n, std::min(k, 4 * n), dis2); int ans = 0; for (int i = 1; i <= std::min(k, 4 * n); ++i) if (dis1[n][i] != 1e18) ans += dis1[n][i]; ans %= kMod; for (int i = 1; i <= m; ++i) { int dis1[2] = {(int)1e18, (int)1e18}; int dis2[2] = {(int)1e18, (int)1e18}; int dis3[2] = {(int)1e18, (int)1e18}; int dis4[2] = {(int)1e18, (int)1e18}; for (int j = 0; j <= 2 * n; ++j) { dis1[j & 1] = std::min(dis1[j & 1], ::dis1[u[i]][j] - j * w[i]); dis2[j & 1] = std::min(dis2[j & 1], ::dis1[v[i]][j] - j * w[i]); dis3[j & 1] = std::min(dis3[j & 1], ::dis2[u[i]][j] - j * w[i]); dis4[j & 1] = std::min(dis4[j & 1], ::dis2[v[i]][j] - j * w[i]); } a[0][i] = a[1][i] = w[i]; b[0][i] = std::min({dis1[0] + dis4[1], dis1[1] + dis4[0], dis2[0] + dis3[1], dis2[1] + dis3[0]}); b[1][i] = std::min({dis1[0] + dis4[0], dis1[1] + dis4[1], dis2[0] + dis3[0], dis2[1] + dis3[1]}); } for (int o = 0; o < 2; ++o) { int sum = 0; for (int i = 1; i <= m; ++i) { int L = 4 * n + 1, R = k; for (int j = 1; j <= m; ++j) { if (j == i) continue; int l, r; if (j < i) std::tie(l, r) = get(a[o][j], b[o][j], a[o][i], b[o][i]); else std::tie(l, r) = get(a[o][j], b[o][j] - 1, a[o][i], b[o][i]); L = std::max(L, l), R = std::min(R, r); } if (b[o][i] < 1e17) { int l = (L - 1 - o) / 2 + 1, r = (R - o) / 2; if (l <= r) { ans += (r - l + 1) * (b[o][i] % kMod) % kMod; ans += (l + r) * (r - l + 1) % kMod * a[o][i] % kMod + o * (r - l + 1) * (a[o][i] % kMod) % kMod; } } if (L <= R) sum += R - L + 1; } } ans = (ans % kMod + kMod) % kMod; std::cout << ans << '\n'; }
int32_t main() { #ifdef ORZXKR freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0); int T = 1; std::cin >> T; while (T--) dickdreamer(); std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
|