/*
* 此题同bzoj2725
* 增加了枚举边的操作
*/
#include <bits/stdc++.h>
const int N = 2e5 + 10;// oo = 999999999;
#define LL long long
const LL oo = 9e18;
int n, m, S, T;
int Short_path[N], Snum[N], Tnum[N], Id[N], path_js;
bool vis[N];
int head[N], now;
struct Node {int u, v, w, nxt;} G[N << 1];
LL dis_s[N], dis_t[N];
LL Minn[N << 2], Ans[N];
inline void Add(int u, int v, int w) {
G[++ now].v = v, G[now].w = w, G[now].nxt = head[u], head[u] = now;
}
struct Node_ {
int u; LL dis;
bool operator < (const Node_ a) const {return dis > a.dis;}
};
std:: priority_queue <Node_> Q;
void Dijkstra(int start, LL dis_[]) {
for(int i = 1; i <= n; i ++) dis_[i] = oo, vis[i] = 0;
Node_ now; now = (Node_) {start, 0}; dis_[start] = 0;
Q.push(now);
while(!Q.empty()) {
Node_ topp = Q.top();
Q.pop();
if(vis[topp.u]) continue;
vis[topp.u] = 1;
for(int i = head[topp.u]; ~ i; i = G[i].nxt) {
int v = G[i].v;
if(dis_[v] > dis_[topp.u] + G[i].w) {
dis_[v] = dis_[topp.u] + G[i].w;
Q.push((Node_) {v, dis_[v]});
}
}
}
}
inline void Bfs(int x, LL dis_[], int bel[]) {
std:: queue <int> Q1;
Q1.push(Short_path[x]);
bel[Short_path[x]] = x;
while(!Q1.empty()) {
int topp = Q1.front();
Q1.pop();
for(int i = head[topp]; ~ i; i = G[i].nxt) {
int v = G[i].v;
if(!Id[v] && !bel[v] && dis_[v] == dis_[topp] + G[i].w) {
bel[v] = x;
Q1.push(v);
}
}
}
}
#define lson jd << 1
#define rson jd << 1 | 1
void Sec_G(int l ,int r, int jd, int x, int y, LL num) {
if(x <= l && r <= y) {
Minn[jd] = std:: min(Minn[jd], (LL)num);
return ;
}
int mid = (l + r) >> 1;
if(x <= mid) Sec_G(l, mid, lson, x, y, num);
if(y > mid) Sec_G(mid + 1, r, rson, x, y, num);
}
void Dfs_tree(int l, int r, int jd) {
if(l == r) {
Ans[l] = Minn[jd];
return ;
}
int mid = (l + r) >> 1;
Minn[lson] = std:: min(Minn[lson], Minn[jd]);
Minn[rson] = std:: min(Minn[rson], Minn[jd]);
Dfs_tree(l, mid, lson), Dfs_tree(mid + 1, r, rson);
}
#define gc getchar()
inline LL read() {
LL x = 0; char c = gc;
while(c < '0' || c > '9') c = gc;
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
return x;
}
bool visit[N << 1];
int main() {
n = read(), m = read();
for(int i = 1; i <= (N << 2); i ++) Minn[i] = oo;
for(int i = 1; i <= n; i ++) head[i] = -1;
for(int i = 1; i <= m; i ++) {
int u = read(), v = read(), w = read();
Add(u, v, w), Add(v, u, w);
}
S = 1, T = n;
Dijkstra(S, dis_s);
Dijkstra(T, dis_t);
for(int i = S; i != T; i = i) {
// visit[i] = 1;
Short_path[++ path_js] = i;
Id[i] = path_js;
for(int j = head[i]; ~ j; j = G[j].nxt) {
if(dis_t[i] == G[j].w + dis_t[G[j].v]) {
i = G[j].v;
visit[j] = 1;
break;
}
}
}
Short_path[path_js + 1] = T, Id[T] = path_js + 1;
for(int i = 1; i <= path_js; i ++) Bfs(i, dis_s, Snum);
for(int i = path_js + 1; i >= 1; i --) Bfs(i, dis_t, Tnum);
for(int i = 1; i <= n; i ++) {
for(int j = head[i]; ~ j; j = G[j].nxt) {
int v = G[j].v;
if(visit[j]) continue;
if(Snum[i] < Tnum[v] && Snum[i] && Tnum[v]) {
Sec_G(1, path_js, 1, Snum[i], Tnum[v] - 1, dis_s[i] + G[j].w + dis_t[v]);
}
}
}
Dfs_tree(1, path_js, 1);
LL Dis = 0, js;
for(int i = 1; i <= path_js; i ++) {
if(Ans[i] > Dis && Ans[i] != oo) Dis = Ans[i], js = 1;
else if(Ans[i] == Dis) js ++;
}
if(Dis == dis_s[T]) js += m - path_js;
std:: cout << Dis << " " << js;
return 0;
}
?