#include using namespace std; using ll = long long; template using min_priority_queue = priority_queue, greater>; using pii = pair; using pll = pair; using Graph = vector>; const ll INF = 1LL << 60; template void chmax(T& a, T b) { if (b > a) a = b; } template void chmin(T& a, T b) { if (b < a) a = b; } template std::ostream& operator<<(std::ostream& os, const pair& x) noexcept { return os << "(" << x.first << ", " << x.second << ")"; } template void print_vector(vector a) { cout << '['; for (int i = 0; i < a.size(); i++) { cout << a[i]; if (i != a.size() - 1) { cout << ", "; } } cout << ']' << endl; } typedef ll idx; typedef ll element; typedef std::function Query; class BinarySearch { public: // コンストラクタ BinarySearch(); // [left, right)の範囲で探索する BinarySearch(Query, idx left, idx right, bool ascending = true); // 要素xが存在するかどうかを判定し、存在したらそのインデックスを、存在しなかったら-1を返す idx find(element x) const; // 要素xの個数をカウントする ll count(element x) const; // ascending = true のとき: f(idx)>=xを満たす最小のidxを求める // ascending = false のとき: f(idx)= left) { idx mid = left + (right - left) / 2; element ret = query_(mid); if (ret == x) return mid; else if (!ascending_ ^ (ret > x)) right = mid - 1; else left = mid + 1; } return -1; } ll BinarySearch::count(element x) const { idx a = bound(x); idx b = bound(x + 1); return std::abs(a - b); } idx BinarySearch::bound(element x) const { idx ng = left_ - 1; idx ok = right_; while (abs(ok - ng) > 1) { idx mid = (ok + ng) / 2; if (!ascending_ ^ (query_(mid) >= x)) ok = mid; else ng = mid; } return ok; } vector bfs(Graph& g, int start, ll weight) { ll N = g.size(); queue q; vector dist(N, -1); vector prevs(N, -1); dist[start] = 0; q.push(start); while (true) { if (q.empty()) break; auto current = q.front(); q.pop(); for (auto& v : g[current]) { if (weight > v.second) continue; if (dist[v.first] == -1) { dist[v.first] = dist[current] + 1; prevs[v.first] = current; q.push(v.first); } } } return prevs; } ll N, M; Graph G; ll f(ll weight) { auto prevs = bfs(G, 0, weight); if (prevs[N - 1] == -1) return false; return true; } int main() { ios::sync_with_stdio(false); std::cin.tie(nullptr); cin >> N >> M; G.resize(N); for (int i = 0; i < M; i++) { ll a, b, c; cin >> a >> b >> c; a--; b--; G[a].push_back({b, c}); G[b].push_back({a, c}); } auto bs = BinarySearch(f, 0, 1000000010, false); auto best_weight = bs.bound(1) - 1; auto prevs = bfs(G, 0, best_weight); ll current = N - 1; int cnt = 0; while (true) { if (current == 0) break; cnt++; current = prevs[current]; } std::cout << best_weight << ' ' << cnt << "\n"; return 0; }