#include #include #include #include using namespace std; 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; 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; } // 仮想頂点 0 から全頂点 1..N への重み 0 の辺を考慮した Bellman-Ford vector h(N + 1, INF); h[0] = 0; // 仮想頂点 0 の距離を 0 とする // input_edges に (0 -> i, 0) の辺を仮想的に含めて N 回更新 vector bf_edges = input_edges; for (int i = 1; i <= N; ++i) { bf_edges.push_back({0, i, 0}); } for (int i = 0; i <= N; ++i) { bool updated = false; for (const auto& edge : bf_edges) { if (h[edge.u] != INF && h[edge.v] > h[edge.u] + edge.t) { h[edge.v] = h[edge.u] + edge.t; updated = true; } } if (!updated) break; } // 辺の重みを非負化して隣接リストを構築 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}); } long long min_cost = INF; long long min_count = 0; // 各頂点からの Dijkstra 法 for (int A = 1; A <= N; ++A) { vector dist(N + 1, INF); 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}); } } } // コストの復元と最小値の集計 for (int B = 1; B <= N; ++B) { if (A == B || dist[B] == INF) continue; // 元の最短距離: real_dist = dist[B] - h[A] + h[B] long long real_dist = dist[B] - h[A] + h[B]; long long cost = real_dist + P[A] + P[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; }