前端知識梳理——CSS基礎
阿新 • • 發佈:2020-08-26
隨便寫寫吧…
顯然方程式 \(f_{t,u}\) 表示 \(t\) 時間在 \(u\) 的最大貢獻。
\(f_{t,u} = \max\{f_{t-w,v} + c_u\}\)。
看到這範圍絕對是矩陣快速冪了…
等等邊權不為\(1\)?
那就構造一個長度為 \(5 \times n\) 的向量嘛,然後每過一個時間就會移動。
我們令 \(id(i,j)\) 為 \(position\) 為 \(i\) 的時候,當前時間為 \(6-j\) 的狀態。
然後轉移矩陣是考慮 \(id(i,j+1) \to id(i,j)\) 的,然後連上邊,注意有重邊,如果沒有注意的話會有奇奇怪怪的問題。
如果有一條 \(\{u, v, w\}\)
base[0][id(u, 6 - w)][id(v, 5)] = c[v];
實際意義是滿足方程式。(
然後就可以轉移了。
預處理 \(\log_2 10^9 = 30\) 個矩陣,向量乘矩陣的複雜度是 \((5n)^2\) 的。
所以複雜度是 \(((5n)^3 + (5n)^2k)\times \log_2 t\)。
#include <bits/stdc++.h> #define FOR(i, x, y) for (int i = x; i <= y; i++) #define ROF(i, x, y) for (int i = x; i >= y; i--) int n, m, T, k; int c[51]; struct buf { int t, x, y; } q[201]; struct Matrix { long long a[251][251]; Matrix() { memset(a, 0xc0, sizeof(a)); } long long* operator[](int x) { return a[x]; } } base[31]; struct Vector { long long a[251]; Vector() { memset(a, 0xc0, sizeof(a)); } long long& operator[](int x) { return a[x]; } } answer; int lim; Matrix mul(Matrix a, Matrix b) { Matrix c; FOR(i, 1, lim) FOR(j, 1, lim) FOR(k, 1, lim) c[i][j] = std::max(c[i][j], a[i][k] + b[k][j]); return c; } Vector mul(Vector a, Matrix b) { Vector c; FOR(i, 1, lim) FOR(j, 1, lim) c[i] = std::max(c[i], a[j] + b[j][i]); return c; } int id(int x, int y) { return x + (y - 1) * n; } int main() { #ifdef LOCAL freopen("testdata.txt", "r", stdin); #endif std::ios::sync_with_stdio(false); std::cin.tie(NULL); std::cin >> n >> m >> T >> k; lim = n * 5; FOR(i, 1, n) std::cin >> c[i]; FOR(i, 1, m) { int u, v, w; std::cin >> u >> v >> w; base[0][id(u, 6 - w)][id(v, 5)] = c[v]; } FOR(i, 1, k) { int t, x, y; std::cin >> t >> x >> y; q[i] = {t, x, y}; } std::sort(q + 1, q + k + 1, [](buf x, buf y) { return x.t < y.t; }); FOR(i, 1, n) FOR(j, 1, 4) base[0][id(i, j + 1)][id(i, j)] = 0; FOR(i, 1, 30) base[i] = mul(base[i - 1], base[i - 1]); answer[id(1, 5)] = c[1]; FOR(i, 1, k) { int t = q[i].t - q[i - 1].t; FOR(j, 0, 30) if (t >> j & 1) answer = mul(answer, base[j]); answer[id(q[i].x, 5)] += q[i].y; } int t = T - q[k].t; FOR(j, 0, 30) if (t >> j & 1) answer = mul(answer, base[j]); std::cout << std::max(answer[id(1, 5)], -1ll) << '\n'; return 0; }