#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int INF = 1e9;
const int MAXN = 100000;
const int MAXM = 500000;
struct Edge {
int to, cost;
};
vector<Edge> G[MAXN + 1], G_rev[MAXN + 1];
int price[MAXN + 1];
int D[MAXN + 1], F[MAXN + 1];
bool vis[MAXN + 1];
void Dijkstra(int start, vector<Edge> G[], int dist[], bool isMin) {
priority_queue<pair<int, int>, vector<pair<int, int>>, less<pair<int, int>>> pq;
memset(vis, false, sizeof(vis));
fill(dist, dist + MAXN + 1, isMin ? INF : 0);
dist[start] = price[start];
pq.push({ price[start], start });
while (!pq.empty()) {
int d = pq.top().first;
int u = pq.top().second;
pq.pop();
if (vis[u]) continue;
vis[u] = true;
for (Edge e : G[u]) {
int v = e.to;
if (isMin) {
if (dist[v] > min(dist[u], price[v])) {
dist[v] = min(dist[u], price[v]);
pq.push({ dist[v], v });
}
}
else {
if (dist[v] < max(dist[u], price[v])) {
dist[v] = max(dist[u], price[v]);
pq.push({ dist[v], v });
}
}
}
}
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
cin >> price[i];
}
for (int i = 0; i < m; ++i) {
int x, y, z;
cin >> x >> y >> z;
G[x].push_back({ y, 0 });
G_rev[y].push_back({ x, 0 });
if (z == 2) {
G[y].push_back({ x, 0 });
G_rev[x].push_back({ y, 0 });
}
}
Dijkstra(1, G, D, true);
Dijkstra(n, G_rev, F, false);
int maxProfit = 0;
for (int i = 1; i <= n; ++i) {
if (F[i] > D[i]) {
maxProfit = max(maxProfit, F[i] - D[i]);
}
}
cout << maxProfit << endl;
return 0;
}