#include #include #include #include using namespace std; // 十分に大きな値を無限大(INF)として定義 const long long INF = 1e18; // 隣接リスト用の辺構造体 struct Edge { int to; long long weight; }; // 入力データ保持用の辺構造体 struct InputEdge { int u, v; long long t; }; int main() { // 標準入出力の高速化 ios_base::sync_with_stdio(false); cin.tie(nullptr); int N, M; if (!(cin >> N >> M)) return 0; // 基本コスト P の読み込み (1-indexed) vector P(N + 1); for (int i = 1; i <= N; ++i) { cin >> P[i]; } // 辺の読み込み vector input_edges(M); for (int i = 0; i < M; ++i) { cin >> input_edges[i].u >> input_edges[i].v >> input_edges[i].t; } // 1. Bellman-Ford法によるポテンシャル h の計算 // 全ての頂点に仮想頂点から重み0の辺があるものとし、初期値0で更新を行う vector h(N + 1, 0); for (int i = 0; i < N; ++i) { bool updated = false; for (const auto& edge : input_edges) { if (h[edge.v] > h[edge.u] + edge.t) { h[edge.v] = h[edge.u] + edge.t; updated = true; } } if (!updated) break; // 更新がなくなったら早期終了 } // 2. 辺の重みの書き換え (非負化) と隣接リストの構築 vector> adj(N + 1); for (const auto& edge : input_edges) { long long w_prime = edge.t + h[edge.u] - h[edge.v]; adj[edge.u].push_back({edge.v, w_prime}); } // 3. 各頂点からのDijkstra法 int min_cost = INF; // intにしてオーバーフローを狙う long long min_count = 0; for (int A = 1; A <= N; ++A) { vector dist(N + 1, INF); // 最小ヒープを構築 (pair<距離, 頂点番号>) priority_queue, vector>, greater>> pq; dist[A] = 0; pq.push({0, A}); while (!pq.empty()) { auto [d_u, u] = pq.top(); pq.pop(); if (d_u > dist[u]) continue; for (const auto& edge : adj[u]) { int v = edge.to; long long w_prime = edge.weight; if (dist[v] > d_u + w_prime) { dist[v] = d_u + w_prime; pq.push({dist[v], v}); } } } // 始点 A から到達できた各頂点 B (A != B) に対してコストを計算・集計 long long const_A = P[A] - h[A]; for (int B = 1; B <= N; ++B) { if (A == B || dist[B] == INF) continue; // 変形したコスト式から元のコストを復元 long long cost = dist[B] + const_A + P[B] + h[B]; if (cost < min_cost) { min_cost = cost; min_count = 1; } else if (cost == min_cost) { min_count++; } } } // 出力処理 if (min_cost == INF) { cout << -1 << "\n"; } else { cout << min_cost << " " << min_count << "\n"; } return 0; }