/*
题意:一无向图,问至少要割掉几条边破坏最短路,问最多能割掉几条边还能保持最短路
SPFA+Dinic:SPFA求最短路时,用cnt[i]记录到i最少要几条边,第二个答案是m - cnt[n]
最大流==最小割,套个Dinic模板,以后再理解算法。。。
*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int MAXN = 2e3 + 10;
const int MAXM = 6e4 + 10;
const int INF = 0x3f3f3f3f;
struct Edge {
int v, w;
};
struct Flow {
int v, cap, rev;
};
bool vis[MAXN];
int cnt[MAXN];
int d[MAXN];
int lv[MAXN];
int it[MAXN];
vector<Edge> G[MAXN];
vector<Flow> F[MAXN];
int n, m;
void add_edge(int u, int v, int cap) {
F[u].push_back ((Flow) {v, cap, (int) F[v].size ()});
F[v].push_back ((Flow) {u, 0, (int) F[u].size ()-1});
}
void BFS(int s) {
memset (lv, -1, sizeof (lv));
queue<int> Q; Q.push (s); lv[s] = 0;
while (!Q.empty ()) {
int u = Q.front (); Q.pop ();
for (int i=0; i<F[u].size (); ++i) {
Flow &e = F[u][i];
if (e.cap > 0 && lv[e.v] < 0) {
lv[e.v] = lv[u] + 1;
Q.push (e.v);
}
}
}
}
int DFS(int u, int t, int f) {
if(u == t) return f;
vis[u] = true;
for (int &i=it[u]; i<F[u].size (); ++i) {
Flow &e = F[u][i];
if (e.cap > 0 && lv[u] < lv[e.v]) {
int d = DFS (e.v, t, min (f, e.cap));
if (d > 0) {
e.cap -= d; F[e.v][e.rev].cap += d;
return d;
}
}
}
return 0;
}
int Dinic(int s, int t) {
int flow = 0, f;
for (; ;) {
BFS (s);
if (lv[t] < 0) return flow;
memset (it, 0, sizeof (it));
while ((f = DFS (s, t, INF)) > 0) flow += f;
}
}
void build_graph(void) {
for (int i=1; i<=n; ++i) {
for (int j=0; j<G[i].size (); ++j) {
Edge &e = G[i][j];
if (d[i] + e.w == d[e.v]) {
add_edge (i, e.v, 1);
add_edge (e.v, i, 0);
}
}
}
}
void SPFA(int s) {
for (int i=1; i<=n; ++i) {
d[i] = (i == s) ? 0 : INF;
cnt[i] = (i == s) ? 0 : INF;
}
memset (vis, false, sizeof (vis)); vis[s] = true;
queue<int> Q; Q.push (s);
while (!Q.empty ()) {
int u = Q.front (); Q.pop ();
vis[u] = false;
for (int i=0; i<G[u].size (); ++i) {
int v = G[u][i].v, w = G[u][i].w;
if (d[v] == d[u] + w) cnt[v] = min (cnt[v], cnt[u] + 1);
if (d[v] > d[u] + w) {
d[v] = d[u] + w; cnt[v] = cnt[u] + 1;
if (!vis[v]) {
vis[v] = true; Q.push (v);
}
}
}
}
}
int main(void) { //HDOJ 5294 Tricks Device
//freopen ("G.in", "r", stdin);
while (scanf ("%d%d", &n, &m) == 2) {
for (int i=1; i<=n; ++i) G[i].clear ();
for (int i=1; i<=n; ++i) F[i].clear ();
for (int i=1; i<=m; ++i) {
int u, v, w; scanf ("%d%d%d", &u, &v, &w);
G[u].push_back ((Edge) {v, w});
G[v].push_back ((Edge) {u, w});
}
SPFA (1);
build_graph ();
printf ("%d %d
", Dinic (1, n), m - cnt[n]);
}
return 0;
}