#include <iostream> #include <vector> #include <queue> #include <set> #include <tuple> #include <algorithm> #include <limits> using namespace std; struct Amplifier { int from, to; long long w; }; struct State { int node; long long L, R; }; vector<vector<Amplifier>> forwardGraph; vector<vector<Amplifier>> revGraph; vector<long long> capacity; vector< set<long long> > reached; int n; long long LIMIT = 10000; long long ceilDiv(long long a, long long b) { return (a + b - 1) / b; } bool isContained(const set<pair<long long, long long>> &intervals, long long L, long long R) { auto it = intervals.upper_bound({L, numeric_limits<long long>::max()}); if (it != intervals.begin()) { --it; if (it->first <= L && it->second >= R) return true; } return false; } pair<long long, long long> mergeInterval(set<pair<long long, long long>> &intervals, long long L, long long R) { auto it = intervals.lower_bound({L, -1}); if (it != intervals.begin()) { auto prev = it; prev--; if (prev->second >= L) { L = min(L, prev->first); R = max(R, prev->second); intervals.erase(prev); } } while (it != intervals.end() && it->first <= R) { L = min(L, it->first); R = max(R, it->second); auto tmp = it; it++; intervals.erase(tmp); } intervals.insert({L, R}); return {L, R}; } bool check(long long low, long long high) { if (low > high) return false; queue<State> q; q.push({n - 1, low, high}); vector< set<pair<long long, long long>> > visited(n); visited[n - 1].insert({low, high}); while (!q.empty()) { State cur = q.front(); q.pop(); auto lower = reached[cur.node].lower_bound(cur.L); if (lower != reached[cur.node].end() && *lower <= cur.R) { return true; } for (auto & : revGraph[cur.node]) { long long newLow = max((long long)1, ceilDiv(cur.L, amp.w)); long long newHigh = min(capacity[amp.from], cur.R / amp.w); if (newLow > newHigh) continue; if (isContained(visited[amp.from], newLow, newHigh)) continue; pair<long long, long long> merged = mergeInterval(visited[amp.from], newLow, newHigh); q.push({amp.from, merged.first, merged.second}); } } return false; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { int m; cin >> n >> m; capacity.resize(n); for (int i = 0; i < n; i++) { cin >> capacity[i]; } forwardGraph.assign(n, vector<Amplifier>()); revGraph.assign(n, vector<Amplifier>()); for (int i = 0; i < m; i++) { int a, b; long long w; cin >> a >> b >> w; forwardGraph[a - 1].push_back({a - 1, b - 1, w}); revGraph[b - 1].push_back({a - 1, b - 1, w}); } reached.assign(n, set<long long>()); queue<pair<int, long long>> bfsQueue; reached[0].insert(1); bfsQueue.push({0, 1}); while (!bfsQueue.empty()) { auto [router, power] = bfsQueue.front(); bfsQueue.pop(); for (auto & : forwardGraph[router]) { int nextRouter = amp.to; long long newPower = power * amp.w; if (newPower > capacity[nextRouter]) { continue; } if (reached[nextRouter].find(newPower) == reached[nextRouter].end() && newPower < LIMIT) { reached[nextRouter].insert(newPower); bfsQueue.push({nextRouter, newPower}); } } } long long low = 1, high = capacity[n - 1], result = -1; if (!check(low, high)) { cout << -1 << endl; continue; } while (low <= high) { long long mid = (low + high) / 2; if (check(mid, high)) { result = mid; low = mid + 1; } else { high = mid - 1; } } cout << result << endl; } return 0; }
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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | #include <iostream> #include <vector> #include <queue> #include <set> #include <tuple> #include <algorithm> #include <limits> using namespace std; struct Amplifier { int from, to; long long w; }; struct State { int node; long long L, R; }; vector<vector<Amplifier>> forwardGraph; vector<vector<Amplifier>> revGraph; vector<long long> capacity; vector< set<long long> > reached; int n; long long LIMIT = 10000; long long ceilDiv(long long a, long long b) { return (a + b - 1) / b; } bool isContained(const set<pair<long long, long long>> &intervals, long long L, long long R) { auto it = intervals.upper_bound({L, numeric_limits<long long>::max()}); if (it != intervals.begin()) { --it; if (it->first <= L && it->second >= R) return true; } return false; } pair<long long, long long> mergeInterval(set<pair<long long, long long>> &intervals, long long L, long long R) { auto it = intervals.lower_bound({L, -1}); if (it != intervals.begin()) { auto prev = it; prev--; if (prev->second >= L) { L = min(L, prev->first); R = max(R, prev->second); intervals.erase(prev); } } while (it != intervals.end() && it->first <= R) { L = min(L, it->first); R = max(R, it->second); auto tmp = it; it++; intervals.erase(tmp); } intervals.insert({L, R}); return {L, R}; } bool check(long long low, long long high) { if (low > high) return false; queue<State> q; q.push({n - 1, low, high}); vector< set<pair<long long, long long>> > visited(n); visited[n - 1].insert({low, high}); while (!q.empty()) { State cur = q.front(); q.pop(); auto lower = reached[cur.node].lower_bound(cur.L); if (lower != reached[cur.node].end() && *lower <= cur.R) { return true; } for (auto & : revGraph[cur.node]) { long long newLow = max((long long)1, ceilDiv(cur.L, amp.w)); long long newHigh = min(capacity[amp.from], cur.R / amp.w); if (newLow > newHigh) continue; if (isContained(visited[amp.from], newLow, newHigh)) continue; pair<long long, long long> merged = mergeInterval(visited[amp.from], newLow, newHigh); q.push({amp.from, merged.first, merged.second}); } } return false; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { int m; cin >> n >> m; capacity.resize(n); for (int i = 0; i < n; i++) { cin >> capacity[i]; } forwardGraph.assign(n, vector<Amplifier>()); revGraph.assign(n, vector<Amplifier>()); for (int i = 0; i < m; i++) { int a, b; long long w; cin >> a >> b >> w; forwardGraph[a - 1].push_back({a - 1, b - 1, w}); revGraph[b - 1].push_back({a - 1, b - 1, w}); } reached.assign(n, set<long long>()); queue<pair<int, long long>> bfsQueue; reached[0].insert(1); bfsQueue.push({0, 1}); while (!bfsQueue.empty()) { auto [router, power] = bfsQueue.front(); bfsQueue.pop(); for (auto & : forwardGraph[router]) { int nextRouter = amp.to; long long newPower = power * amp.w; if (newPower > capacity[nextRouter]) { continue; } if (reached[nextRouter].find(newPower) == reached[nextRouter].end() && newPower < LIMIT) { reached[nextRouter].insert(newPower); bfsQueue.push({nextRouter, newPower}); } } } long long low = 1, high = capacity[n - 1], result = -1; if (!check(low, high)) { cout << -1 << endl; continue; } while (low <= high) { long long mid = (low + high) / 2; if (check(mid, high)) { result = mid; low = mid + 1; } else { high = mid - 1; } } cout << result << endl; } return 0; } |