#include <bits/stdc++.h>
using namespace std;
template <typename T> void set_min(T& a, const T& b){
if(b < a) a = b;
}
template <typename T> void set_max(T& a, const T& b){
if(b > a) a = b;
}
void solve(){
int N, M;
cin >> N >> M;
vector<int> cap(N);
for(int i = 0; i < N; i++) cin >> cap[i];
vector<vector<pair<int, int> > > adj(N);
vector<vector<pair<int, int> > > radj(N);
int S = (int)sqrt(cap[N-1]) + 2;
assert((S-1) * (S-1) >= cap[N-1]);
for(int i = 0; i < M; i++){
int u, v;
cin >> u >> v;
u--; v--;
int w;
cin >> w;
adj[u].push_back({v, w});
radj[v].push_back({u, w});
}
int ans = -1;
if(0 == N-1) ans = max(ans, 1);
vector<vector<int>> reach_src(N, vector<int>(S, 0));
reach_src[0][1] = 1;
for(int val = 1; val < S; val++){
queue<int> q;
for(int v = 0; v < N; v++){
if(reach_src[v][val]) q.push(v);
}
while(!q.empty()){
int v = q.front();
q.pop();
for(auto [w, wgt] : adj[v]){
if(wgt == 1){
if(val <= cap[w] && !reach_src[w][val]){
reach_src[w][val] = 1;
q.push(w);
}
}
}
}
for(int v = 0; v < N; v++){
for(auto [w, wgt] : adj[v]){
if(reach_src[v][val]){
if((S-1) / wgt >= val && val * wgt <= cap[w]){
reach_src[w][val * wgt] = 1;
}
}
}
}
}
vector<vector<int> > reach_src_best(N, vector<int>(S));
for(int i = 0; i < N; i++){
for(int s = 1; s < S; s++){
reach_src_best[i][s] = reach_src_best[i][s-1];
if(reach_src[i][s]) reach_src_best[i][s] = s;
}
}
// from the sink, compute floor(p_i / prod(weights))
// what is the maximum min bound for each fixed prod(weights)
vector<vector<int> > best_sink(N, vector<int>(S, 0));
best_sink[N-1][1] = cap[N-1];
for(int val = 1; val < S; val++){
priority_queue<pair<int,int> > pq;
for(int v = 0; v < N; v++){
if(best_sink[v][val]) pq.push({best_sink[v][val], v});
}
while(!pq.empty()){
auto [best, v] = pq.top();
pq.pop();
if(best_sink[v][val] != best) continue;
for(auto [w, wgt] : radj[v]){
if(wgt == 1){
int nbound = min(best_sink[v][val], cap[w]);
if(nbound > best_sink[w][val]){
best_sink[w][val] = nbound;
pq.push({best_sink[w][val], w});
}
}
}
}
for(int v = 0; v < N; v++){
for(auto [w, wgt] : radj[v]){
if(wgt > 1 && (S-1) / wgt >= val){
set_max(best_sink[w][val * wgt], min(best_sink[v][val] / wgt, cap[w]));
}
}
}
}
// for(int s = 1; s < S; s++){
// if(reach_src[N-1][s]) set_max(ans, s);
// }
for(int v = 0; v < N; v++){
for(auto [w, wgt] : adj[v]){
for(int factor = 1; factor < S; factor++){
int go = min(best_sink[w][factor] / wgt, cap[v]);
go = min(go, S-1);
int k = reach_src_best[v][go];
if(k) ans = max(ans, k * factor * wgt);
}
}
}
cout << ans << '\n';
}
int main(){
ios_base::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while(T--) solve();
}
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 116 117 118 119 120 121 122 | #include <bits/stdc++.h> using namespace std; template <typename T> void set_min(T& a, const T& b){ if(b < a) a = b; } template <typename T> void set_max(T& a, const T& b){ if(b > a) a = b; } void solve(){ int N, M; cin >> N >> M; vector<int> cap(N); for(int i = 0; i < N; i++) cin >> cap[i]; vector<vector<pair<int, int> > > adj(N); vector<vector<pair<int, int> > > radj(N); int S = (int)sqrt(cap[N-1]) + 2; assert((S-1) * (S-1) >= cap[N-1]); for(int i = 0; i < M; i++){ int u, v; cin >> u >> v; u--; v--; int w; cin >> w; adj[u].push_back({v, w}); radj[v].push_back({u, w}); } int ans = -1; if(0 == N-1) ans = max(ans, 1); vector<vector<int>> reach_src(N, vector<int>(S, 0)); reach_src[0][1] = 1; for(int val = 1; val < S; val++){ queue<int> q; for(int v = 0; v < N; v++){ if(reach_src[v][val]) q.push(v); } while(!q.empty()){ int v = q.front(); q.pop(); for(auto [w, wgt] : adj[v]){ if(wgt == 1){ if(val <= cap[w] && !reach_src[w][val]){ reach_src[w][val] = 1; q.push(w); } } } } for(int v = 0; v < N; v++){ for(auto [w, wgt] : adj[v]){ if(reach_src[v][val]){ if((S-1) / wgt >= val && val * wgt <= cap[w]){ reach_src[w][val * wgt] = 1; } } } } } vector<vector<int> > reach_src_best(N, vector<int>(S)); for(int i = 0; i < N; i++){ for(int s = 1; s < S; s++){ reach_src_best[i][s] = reach_src_best[i][s-1]; if(reach_src[i][s]) reach_src_best[i][s] = s; } } // from the sink, compute floor(p_i / prod(weights)) // what is the maximum min bound for each fixed prod(weights) vector<vector<int> > best_sink(N, vector<int>(S, 0)); best_sink[N-1][1] = cap[N-1]; for(int val = 1; val < S; val++){ priority_queue<pair<int,int> > pq; for(int v = 0; v < N; v++){ if(best_sink[v][val]) pq.push({best_sink[v][val], v}); } while(!pq.empty()){ auto [best, v] = pq.top(); pq.pop(); if(best_sink[v][val] != best) continue; for(auto [w, wgt] : radj[v]){ if(wgt == 1){ int nbound = min(best_sink[v][val], cap[w]); if(nbound > best_sink[w][val]){ best_sink[w][val] = nbound; pq.push({best_sink[w][val], w}); } } } } for(int v = 0; v < N; v++){ for(auto [w, wgt] : radj[v]){ if(wgt > 1 && (S-1) / wgt >= val){ set_max(best_sink[w][val * wgt], min(best_sink[v][val] / wgt, cap[w])); } } } } // for(int s = 1; s < S; s++){ // if(reach_src[N-1][s]) set_max(ans, s); // } for(int v = 0; v < N; v++){ for(auto [w, wgt] : adj[v]){ for(int factor = 1; factor < S; factor++){ int go = min(best_sink[w][factor] / wgt, cap[v]); go = min(go, S-1); int k = reach_src_best[v][go]; if(k) ans = max(ans, k * factor * wgt); } } } cout << ans << '\n'; } int main(){ ios_base::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while(T--) solve(); } |
English