[NOI2020]美食家 題解
阿新 • • 發佈:2020-08-29
考慮拆點\(,\)把每個點拆成\(5\)個點\(,\) \(p_{i,t}(0\leq t \leq 4)\)表示\(t\)秒之後到達點\(i.\)
對於每個正整數\(t,\)把所有的\(p_{i,t}\)連向\(p_{i,t-1}.\)
然後每一條邊\((x,y,t)\)就可以變成\((p_{x,0},p_{y,t-1}),\)就可以矩陣乘法來維護這個東西了\(.\)
不難據此得到轉移矩陣\(A.\)
然後我們相當於要向量乘矩陣\(,\)一共需要乘\(k\)次\(A\)的若干次方\(,\)那麼我們預處理一下\(A^2,A^4,A^8,...A^{2^{30}}\)即可\(.\)
複雜度\(O((nw)^3 \log T+k(nw)^2 \log T).\)
程式碼\(:\)
#include <bits/stdc++.h> #define LL long long using namespace std; const int N = 50,M = 505,K = 205,V = 250; const LL INF = 1ll << 60; int L; struct Mat{ LL a[V][V]; inline void init(){ for (int i = 0; i < L; ++i) for (int j = 0; j < L; ++j) a[i][j] = -INF; } }; struct Vec{ LL a[V]; inline void init(){ for (int i = 0; i < L; ++i) a[i] = -INF; } }; Mat operator * (const Mat A,const Mat B){ static Mat T; T.init(); for (int k = 0; k < L; ++k) for (int i = 0; i < L; ++i) for (int j = 0; j < L; ++j) if (A.a[i][k] + B.a[k][j] > T.a[i][j]) T.a[i][j] = A.a[i][k] + B.a[k][j]; return T; } Vec operator * (const Mat A,const Vec B){ static Vec T; T.init(); for (int i = 0; i < L; ++i) for (int j = 0; j < L; ++j) if (A.a[j][i] + B.a[j] > T.a[i]) T.a[i] = A.a[j][i] + B.a[j]; return T; } int n,m,T,k,c[N]; int ex[M],ey[M],ez[M]; Mat I,Tr,A[30]; Vec st; int nowt; int id[N][5]; struct Festival{ int t,x,y; }ev[K]; int main(){ // freopen("delicacy.in","r",stdin); // freopen("delicacy.out","w",stdout); int i,j; cin >> n >> m >> T >> k; I.init(); L = n * 5; for (i = 0; i < n; ++i) cin >> c[i]; for (i = 0; i < n; ++i) I.a[i][i] = 0; for (i = 0; i < n; ++i) for (j = 0; j < 5; ++j) id[i][j] = j * n + i; for (i = 1; i <= m; ++i) cin >> ex[i] >> ey[i] >> ez[i],--ex[i],--ey[i]; Tr.init(); for (i = 0; i < n; ++i) for (j = 1; j < 5; ++j) Tr.a[id[i][j]][id[i][j-1]] = (j==1) ? (c[i]) : (0); for (i = 1; i <= m; ++i) Tr.a[id[ex[i]][0]][id[ey[i]][ez[i]-1]] = (ez[i]==1) ? (c[ey[i]]) : (0); A[0] = Tr; for (i = 1; i < 30; ++i) A[i] = A[i-1] * A[i-1]; for (i = 1; i <= k; ++i) cin >> ev[i].t >> ev[i].x >> ev[i].y,--ev[i].x; for (i = 1; i <= k; ++i) for (j = i+1; j <= k; ++j) if (ev[j].t < ev[i].t) swap(ev[i],ev[j]); if (ev[k].t != T){ ++k; ev[k].t = T,ev[k].x = ev[k].y = 0; } st.init(); st.a[id[0][0]] = c[0]; nowt = 0; for (i = 1; i <= k; ++i){ int dt = ev[i].t - nowt; for (j = 0; j < 30; ++j) if (dt>>j&1) st = A[j] * st; if (st.a[ev[i].x] >= 0) st.a[ev[i].x] += ev[i].y; nowt = ev[i].t; } if (st.a[0] < 0) st.a[0] = -1; cout << st.a[0] << '\n'; }