#include #include #include #include #include #include using namespace std; const long long INF = 1e18; struct Edge { int u, v, w; }; int main() { ios::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 edges(M); vector>> adj(N + 1); for (int i = 0; i < M; i++) { cin >> edges[i].u >> edges[i].v >> edges[i].w; adj[edges[i].u].push_back({edges[i].v, edges[i].w}); } // 正しいポテンシャル h の計算 (SPFA) vector h(N + 1, 0); queue q; vector in_q(N + 1, true); for (int i = 1; i <= N; i++) q.push(i); while (!q.empty()) { int u = q.front(); q.pop(); in_q[u] = false; for (auto& edge : adj[u]) { int v = edge.first; int w = edge.second; if (h[v] > h[u] + w) { h[v] = h[u] + w; if (!in_q[v]) { q.push(v); in_q[v] = true; } } } } // Johnson の再重み付け vector>> adj_rw(N + 1); for (auto& e : edges) { adj_rw[e.u].push_back({e.v, e.w + h[e.u] - h[e.v]}); } // 【嘘ポイント】ランダム K=200 点のみ Dijkstra vector sources(N); iota(sources.begin(), sources.end(), 1); mt19937 rng(1337); shuffle(sources.begin(), sources.end(), rng); int K = min(N, 200); long long ans_cost = INF; int ans_count = 0; using PLI = pair; for (int i = 0; i < K; i++) { int src = sources[i]; vector dist(N + 1, INF); priority_queue, greater> pq; dist[src] = 0; pq.push({0, src}); while (!pq.empty()) { auto [d, u] = pq.top(); pq.pop(); if (d > dist[u]) continue; for (auto& edge : adj_rw[u]) { int v = edge.first; long long rw = edge.second; if (dist[v] > d + rw) { dist[v] = d + rw; pq.push({dist[v], v}); } } } for (int v = 1; v <= N; v++) { if (src == v || dist[v] == INF) continue; long long real_dist = dist[v] - h[src] + h[v]; long long cost = real_dist + P[src] + P[v]; if (cost < ans_cost) { ans_cost = cost; ans_count = 1; } else if (cost == ans_cost) { ans_count++; } } } if (ans_cost == INF) cout << -1 << "\n"; else cout << ans_cost << " " << ans_count << "\n"; return 0; }