import heapq def dijkstra(s, n, edge): dist = [1 << 63]*n dist[s] = 0 hq = [[0,s]] heapq.heapify(hq) while len(hq) > 0: d,i = heapq.heappop(hq) if dist[i] < d: continue for j,d_1 in edge[i]: if dist[j] > (dist[i] + d_1): dist[j] = dist[i] + d_1 heapq.heappush(hq, [dist[j],j]) return dist import math from bisect import bisect_left, bisect_right from typing import Generic, Iterable, Iterator, List, Tuple, TypeVar, Optional T = TypeVar('T') class SortedMultiset(Generic[T]): BUCKET_RATIO = 16 SPLIT_RATIO = 24 def __init__(self, a: Iterable[T] = []) -> None: "Make a new SortedMultiset from iterable. / O(N) if sorted / O(N log N)" a = list(a) n = self.size = len(a) if any(a[i] > a[i + 1] for i in range(n - 1)): a.sort() bucket_size = int(math.ceil(math.sqrt(n / self.BUCKET_RATIO))) self.a = [a[n * i // bucket_size : n * (i + 1) // bucket_size] for i in range(bucket_size)] def __iter__(self) -> Iterator[T]: for i in self.a: for j in i: yield j def __reversed__(self) -> Iterator[T]: for i in reversed(self.a): for j in reversed(i): yield j def __eq__(self, other) -> bool: return list(self) == list(other) def __len__(self) -> int: return self.size def __repr__(self) -> str: return "SortedMultiset" + str(self.a) def __str__(self) -> str: s = str(list(self)) return "{" + s[1 : len(s) - 1] + "}" def _position(self, x: T) -> Tuple[List[T], int, int]: "return the bucket, index of the bucket and position in which x should be. self must not be empty." for i, a in enumerate(self.a): if x <= a[-1]: break return (a, i, bisect_left(a, x)) def __contains__(self, x: T) -> bool: if self.size == 0: return False a, _, i = self._position(x) return i != len(a) and a[i] == x def count(self, x: T) -> int: "Count the number of x." return self.index_right(x) - self.index(x) def add(self, x: T) -> None: "Add an element. / O(√N)" if self.size == 0: self.a = [[x]] self.size = 1 return a, b, i = self._position(x) a.insert(i, x) self.size += 1 if len(a) > len(self.a) * self.SPLIT_RATIO: mid = len(a) >> 1 self.a[b:b+1] = [a[:mid], a[mid:]] def _pop(self, a: List[T], b: int, i: int) -> T: ans = a.pop(i) self.size -= 1 if not a: del self.a[b] return ans def discard(self, x: T) -> bool: "Remove an element and return True if removed. / O(√N)" if self.size == 0: return False a, b, i = self._position(x) if i == len(a) or a[i] != x: return False self._pop(a, b, i) return True def lt(self, x: T) -> Optional[T]: "Find the largest element < x, or None if it doesn't exist." for a in reversed(self.a): if a[0] < x: return a[bisect_left(a, x) - 1] def le(self, x: T) -> Optional[T]: "Find the largest element <= x, or None if it doesn't exist." for a in reversed(self.a): if a[0] <= x: return a[bisect_right(a, x) - 1] def gt(self, x: T) -> Optional[T]: "Find the smallest element > x, or None if it doesn't exist." for a in self.a: if a[-1] > x: return a[bisect_right(a, x)] def ge(self, x: T) -> Optional[T]: "Find the smallest element >= x, or None if it doesn't exist." for a in self.a: if a[-1] >= x: return a[bisect_left(a, x)] def __getitem__(self, i: int) -> T: "Return the i-th element." if i < 0: for a in reversed(self.a): i += len(a) if i >= 0: return a[i] else: for a in self.a: if i < len(a): return a[i] i -= len(a) raise IndexError def pop(self, i: int = -1) -> T: "Pop and return the i-th element." if i < 0: for b, a in enumerate(reversed(self.a)): i += len(a) if i >= 0: return self._pop(a, ~b, i) else: for b, a in enumerate(self.a): if i < len(a): return self._pop(a, b, i) i -= len(a) raise IndexError def bisect(self, x: T) -> int: "Count the number of elements < x." ans = 0 for a in self.a: if a[-1] >= x: return ans + bisect_left(a, x) ans += len(a) return ans def index_right(self, x: T) -> int: "Count the number of elements <= x." ans = 0 for a in self.a: if a[-1] > x: return ans + bisect_right(a, x) ans += len(a) return ans class ConvexHullTrick: def __init__(self): self.L = SortedMultiset([]) self.n = 0 def check(self,a,b): if self.n == 0: return True x = self.L.bisect((a,b)) if x == 0: aa,bb = self.L[0] if a != aa: return True if b < bb: return True else: return False elif x == self.n: aa,bb = self.L[-1] if a != aa: return True if b < bb: return True else: return False else: al,bl = self.L[x-1] ar,br = self.L[x] if (br-b)*(a-al) >= (b-bl)*(ar-a): return True else: return False def add(self,a,b): # y=ax+bを追加する。 if self.check(a,b): x = self.L.bisect((a,b)) self.L.add((a,b)) self.n += 1 l = x - 1 r = x + 1 while r < self.n: a,b = self.L[r] self.L.discard((a,b)) self.n -= 1 if self.check(a,b): self.L.add((a,b)) self.n += 1 break while l > 0: a,b = self.L[l] self.L.discard((a,b)) l -= 1 self.n -= 1 if self.check(a,b): self.L.add((a,b)) self.n += 1 break def min(self,x): l = 0 r = self.n while r - l > 1: m = (l + r) // 2 a,b = self.L[m] aa,bb = self.L[m-1] if a*x + b <= aa*x + bb: l = m else: r = m a,b = self.L[l] return a*x + b def get(self): return self.L N,M = map(int,input().split()) W = list(map(int,input().split())) G = [[] for i in range(N)] for _ in range(M): u,v,t = map(int,input().split()) u,v = u - 1,v - 1 G[u].append((v,t)) G[v].append((u,t)) CHT = ConvexHullTrick() dist_s = dijkstra(0,N,G) dist_g = dijkstra(N-1,N,G) for i in range(N): w,d = W[i],dist_g[i] CHT.add(w,d) ans = dist_s[N-1] for i in range(N): w,d = W[i],dist_s[i] res = CHT.min(w) + d ans = min(ans,res) print(ans)