#include using namespace std; using ll = long long; //min_ver class LiChaoTree{ struct Line{ long long a, b; long long get(long long x){return a * x + b; } Line(long long a, long long b) : a(a), b(b) {} }; struct Node { Node *left, *right; Line line; Node(Line line) : left(nullptr), right(nullptr), line(line) {} }; const long long inf = 1ll << 60; const Line inf_line = Line{0, inf}; Node *root; long long lx, rx; Node* _add_line(Node *nd, Line line, long long l, long long r){ if(l == r) return nullptr; if(nd == nullptr) return new Node(line); long long m = (l + r) >> 1; bool left = (line.get(l) <= nd->line.get(l)); bool mid = (line.get(m) <= nd->line.get(m)); bool right = (line.get(r) <= nd->line.get(r)); if(left && right)nd->line = line; if(left == right)return nd; if(mid) std::swap(nd->line, line); if(left != mid){ nd->left = _add_line(nd->left, line, l, m); }else{ nd->right = _add_line(nd->right, line, m, r); } return nd; } Node* _add_segment_line(long long a, long long b, Node *nd, Line line, long long l, long long r) { if(r <= a || b <= l) return nd; if(a <= l && r <= b) return _add_line(nd, line, l, r); if(nd == nullptr) nd = new Node(inf_line); long long m = (l + r) >> 1; nd->left = _add_segment_line(a, b, nd->left, line, l, m); nd->right = _add_segment_line(a, b, nd->right, line, m, r); return nd; } long long query(long long x, long long l, long long r){ Node *nd = root; long long res = inf; while(r > l && nd != nullptr) { long long m = (l + r) >> 1; res = std::min(res, nd->line.get(x)); if(x < m) { r = m; nd = nd->left; } else { l = m; nd = nd->right; } } return res; } public: // [xl, xr) LiChaoTree(long long lx, long long rx) : lx(lx), rx(rx), root(nullptr) {} void add_line(long long a, long long b) { Line line(a, b); root = _add_line(root, line, lx, rx); } void add_segment_line(long long a, long long b, long long l, long long r) { Line line = Line{a, b}; root = _add_segment_line(l, r, root, line, lx, rx); } long long get(long long x) { return query(x, lx, rx); } }; template struct segtree { public: segtree() : segtree(0) {} segtree(int n) : segtree(std::vector(n, e())) {} segtree(const std::vector& v) : _n(int(v.size())) { log = ceil_pow2(_n); size = 1 << log; d = std::vector(2 * size, e()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } void set(int p, S x) { assert(0 <= p && p < _n); p += size; d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } S get(int p) { assert(0 <= p && p < _n); return d[p + size]; } const S operator[](int p) const { return get(p); } S operator[](int p) { return get(p); } S prod(int l, int r) { assert(0 <= l && l <= r && r <= _n); S sml = e(), smr = e(); l += size; r += size; while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S all_prod() { return d[1]; } template int max_right(int l) { return max_right(l, [](S x) { return f(x); }); } template int max_right(int l, F f) { assert(0 <= l && l <= _n); assert(f(e())); if (l == _n) return _n; l += size; S sm = e(); do { while (l % 2 == 0) l >>= 1; if (!f(op(sm, d[l]))) { while (l < size) { l = (2 * l); if (f(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; } while ((l & -l) != l); return _n; } template int min_left(int r) { return min_left(r, [](S x) { return f(x); }); } template int min_left(int r, F f) { assert(0 <= r && r <= _n); assert(f(e())); if (r == 0) return 0; r += size; S sm = e(); do { r--; while (r > 1 && (r % 2)) r >>= 1; if (!f(op(d[r], sm))) { while (r < size) { r = (2 * r + 1); if (f(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); } while ((r & -r) != r); return 0; } private: int _n, size, log; std::vector d; int ceil_pow2(int n) { int x = 0; while ((1U << x) < (unsigned int)(n)) x++; return x; } void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } }; using S = pair; S op(S lhs, S rhs){ return min(lhs, rhs); } S e(){ return make_pair(1ll << 60, -1); } int main(){ ios::sync_with_stdio(false); cin.tie(0); int n, m; cin >> n >> m; LiChaoTree LCT(0, 1 << 30); vector tmp(n); for(int i = 0; i < n; i++){ cin >> tmp[i].first; tmp[i].second = i; } segtree seg(tmp); vector>> g(n); vector dp(n, 1ll << 60); priority_queue, vector>, greater>> pq; for(int i = 0; i < m; i++){ int u, v, t; cin >> u >> v >> t; g[--u].emplace_back(--v, t); g[v].emplace_back(u, t); } dp[0] = 0; pq.emplace(0, 0); seg.set(0, e()); while(!pq.empty()){ auto [w, u] = seg.all_prod(); ll d2 = 0; if(u != -1) d2 = LCT.get(w); if(u != -1 && d2 < pq.top().first){ dp[u] = d2; pq.emplace(d2, u); seg.set(u, e()); tie(w, u) = seg.all_prod(); if(u == -1) d2 = 1ll << 62; else d2 = LCT.get(w); } auto [d, v] = pq.top(); pq.pop(); if(d > dp[v]) continue; LCT.add_line(tmp[v].first, d); for(auto &&[u, w] : g[v]){ if(d + w >= dp[u]) continue; dp[u] = d + w; pq.emplace(dp[u], u); } } cout << dp.back() << '\n'; }