/* I will wait for you */ #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <algorithm> #include <iostream> #include <fstream> #include <vector> #include <queue> #include <deque> #include <set> #include <map> #include <string> #define make(a,b) make_pair(a,b) #define fi first #define se second using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; typedef map<int, int> mii; const int maxn = 100010; const int maxm = 1010; const int maxs = 26; const int inf = 0x3f3f3f3f; const int P = 1000000007; const double error = 1e-9; inline ll read() { ll x = 0, f = 1; char ch = getchar(); while (ch > '9' || ch < '0' ) f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); return f * x; } struct edge { int v, w, next; } e[maxn * 2]; int n, m, cnt, sum, root, head[maxn], deep[maxn], del[maxn], size[maxn], val[maxn], K, _ans[2], g[maxn][2], f[maxn][2], dis[maxn], vis[maxn], _max[maxn]; priority_queue<pii, vector<pii>, greater<pii> > q, _next[maxn]; void insert(int u, int v, int w) { e[cnt] = (edge) {v, w, head[u]}, head[u] = cnt++; } void dijkstra() { memset(dis, 0x3f, sizeof dis), dis[1] = 0; for (int i = 1; i <= n; i++) q.push(make(dis[i], i)); for (int i = 1; i <= n; i++) { while (q.top().fi != dis[q.top().se]) q.pop(); int u = q.top().se; q.pop(); for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; if (dis[v] > dis[u] + e[i].w) { dis[v] = dis[u] + e[i].w; q.push(make(dis[v], v)); } } } } void _dfs(int u) { vis[u] = 1; while (!_next[u].empty()) { pii v = _next[u].top(); _next[u].pop(); if (!vis[v.fi]) { insert(u, v.fi, v.se); insert(v.fi, u, v.se); _dfs(v.fi); } } } void find_root(int u, int p) { size[u] = 1, _max[u] = 0; for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; if (v != p && !del[v]) { find_root(v, u), size[u] += size[v]; _max[u] = max(_max[u], size[v]); } } _max[u] = max(_max[u], sum - size[u]); if (_max[u] < _max[root]) root = u; } void __dfs(int u, int p) { if (val[u] > g[deep[u]][0]) g[deep[u]][0] = val[u], g[deep[u]][1] = 0; if (val[u] == g[deep[u]][0]) g[deep[u]][1] += 1; for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; if (v != p && !del[v]) { deep[v] = deep[u] + 1; val[v] = val[u] + e[i].w; __dfs(v, u); } } } void get_size(int u, int p) { size[u] = 1; for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; if (v != p && !del[v]) get_size(v, u), size[u] += size[v]; } } void solve(int u) { del[u] = 1; get_size(u, 0); for (int i = 0; i <= size[u]; i++) f[i][0] = f[i][1] = 0; f[0][0] = 0, f[0][1] = 1; for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; if (!del[v]) { for (int j = 0; j <= size[v]; j++) g[j][0] = g[j][1] = 0; deep[v] = 1, val[v] = e[i].w, __dfs(v, u); for (int j = 1; j <= K && j <= size[v]; j++) { if (g[j][0] + f[K - j][0] > _ans[0]) _ans[0] = g[j][0] + f[K - j][0], _ans[1] = 0; if (g[j][0] + f[K - j][0] == _ans[0]) _ans[1] += g[j][1] * f[K - j][1]; } for (int j = 1; j <= size[v]; j++) { if (g[j][0] > f[j][0]) f[j][0] = g[j][0], f[j][1] = 0; if (g[j][0] == f[j][0]) f[j][1] += g[j][1]; } } } for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; if (!del[v]) { sum = size[u], root = 0; find_root(v, u), solve(root); } } } int main() { n = read(), m = read(), K = read() - 1; memset(head, -1, sizeof head); for (int i = 1; i <= m; i++) { int u =read(), v = read(), w = read(); insert(u, v, w), insert(v, u, w); } dijkstra(); for (int i = 0; i < cnt; i++) if (dis[e[i].v] == dis[e[i ^ 1].v] + e[i].w) _next[e[i ^ 1].v].push(make(e[i].v, e[i].w)); memset(head, -1, sizeof head); cnt = 0, _dfs(1); sum = _max[0] = n, root = 0; find_root(1, 0), solve(root); printf("%d %d\n", _ans[0], _ans[1]); return 0; }