#include #include #include #include #include using namespace std; const long long INF = 1e18; struct Edge { int to; long long cost; }; int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); 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}); } // 辺の評価順をランダムにして、特定のキラーケースを回避する mt19937 rng(42); for (int i = 1; i <= N; ++i) { shuffle(adj[i].begin(), adj[i].end(), rng); } long long min_total_cost = INF; long long min_count = 0; for (int start = 1; start <= N; ++start) { vector dist(N + 1, INF); vector in_queue(N + 1, false); deque dq; dist[start] = 0; dq.push_back(start); in_queue[start] = true; int op_count = 0; // ループ回数の上限(これを超えたら、その時点の暫定解で妥協する) const int OP_LIMIT = 150000; while (!dq.empty()) { int u = dq.front(); dq.pop_front(); in_queue[u] = false; op_count++; if (op_count > OP_LIMIT) break; // TLE逃れ for (auto& edge : adj[u]) { int v = edge.to; long long weight = edge.cost; if (dist[u] + weight < dist[v]) { dist[v] = dist[u] + weight; if (!in_queue[v]) { // SLF (Small Label First) 最適化 if (!dq.empty() && dist[v] < dist[dq.front()]) { dq.push_front(v); } else { dq.push_back(v); } in_queue[v] = true; } } } } for (int v = 1; v <= N; ++v) { if (start == v || dist[v] == INF) continue; long long current_cost = dist[v] + P[start] + P[v]; if (current_cost < min_total_cost) { min_total_cost = current_cost; min_count = 1; } else if (current_cost == min_total_cost) { min_count++; } } } if (min_total_cost == INF) cout << -1 << "\n"; else cout << min_total_cost << " " << min_count << "\n"; return 0; }