#include #include #include #include #include using namespace std; const long long INF = 1e18; struct Edge { int to; long long weight; }; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, m; if (!(cin >> n >> m)) return 0; vector p(n + 1); for (int i = 1; i <= n; ++i) { cin >> p[i]; } vector> adj(n + 1); for (int i = 0; i < m; ++i) { int u, v; long long t; cin >> u >> v >> t; adj[u].push_back({v, t}); } // 1. 超頂点 0 を使って SPFA を 1 回だけ回し、ポテンシャル h を計算 vector h(n + 1, 0); vector in_queue(n + 1, true); queue q; for (int i = 1; i <= n; ++i) q.push(i); while (!q.empty()) { int u = q.front(); q.pop(); in_queue[u] = false; for (const auto& edge : adj[u]) { if (h[u] + edge.weight < h[edge.to]) { h[edge.to] = h[u] + edge.weight; if (!in_queue[edge.to]) { q.push(edge.to); in_queue[edge.to] = true; } } } } // 2. 各ノードからダイクストラ法を N 回回す long long min_cost = INF; long long ways = 0; for (int start = 1; start <= n; ++start) { vector dist(n + 1, INF); priority_queue, vector>, greater>> pq; dist[start] = 0; pq.push({0, start}); while (!pq.empty()) { auto [d, u] = pq.top(); pq.pop(); if (d > dist[u]) continue; for (const auto& edge : adj[u]) { // ジョンソンのアルゴリズムによる非負の重みへの変換 long long new_weight = edge.weight + h[u] - h[edge.to]; if (dist[u] + new_weight < dist[edge.to]) { dist[edge.to] = dist[u] + new_weight; pq.push({dist[edge.to], edge.to}); } } } // 3. 元の最短距離に戻してコストを更新 for (int target = 1; target <= n; ++target) { if (start == target || dist[target] == INF) continue; // 元の最短経路の距離を逆算: dist_real = dist_potential - h[start] + h[target] long long real_dist = dist[target] - h[start] + h[target]; long long current_cost = real_dist + p[start] + p[target]; if (current_cost < min_cost) { min_cost = current_cost; ways = 1; } else if (current_cost == min_cost) { ways++; } } } if (min_cost == INF) { std::println("-1"); } else { std::println("{} {}", min_cost, ways); } return 0; }