#include <iostream>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const ll mxN = 1e5, MOD = 1e9+7, inf = 1e17;
vector<pair<ll,ll>> adj[mxN+1];
ll d[mxN+1], visited[mxN+1], cnt[mxN+1], M[mxN+1],mini[mxN+1];
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n , m;
    cin >> n >> m;
    for(int i = 1;i<=m;i++)
    {
        int u , v, w;
        cin >> u >> v >> w;
        adj[u].push_back({v,w});
    }
    for(int i = 2;i<=n;i++)
    {
        d[i] = mini[i] = inf;
        M[i] = -inf;
    }
    cnt[1] = 1;
    mini[1] = 0;
    M[1] = 0;
    priority_queue<pair<ll,ll>> pq;
    pq.push({0,1}); // distance -- node
    while(!pq.empty())
    {
        int node = pq.top().second;
        pq.pop();
        if(visited[node]) continue;
        visited[node] = true;
        for(auto it : adj[node])
        {
            ll u = it.first, w = it.second;
            ll dist = d[node] + w;
            if(d[u] > dist)
            {
                d[u] = dist;
                mini[u] = mini[node]+1;
                M[u] = M[node]+1;
                cnt[u] = cnt[node];
                pq.push({-dist,u});
            }
            else if(d[u] == dist)
            {
                mini[u] = min(mini[u], mini[node]+1);
                M[u] = max(M[u],M[node]+1);
                cnt[u] = (cnt[u] + cnt[node]);
                if(cnt[u] >= inf) cnt[u]%=MOD;
            }
        }
    }
    cout << d[n] << ' ' << cnt[n] % MOD << ' ' << mini[n] << ' ' << M[n];
    return 0;
}