#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
int add(int x, int y) {
  x += y;
  if (x >= mod) x -= mod;
  return x;
}
int mul(int x, int y) { return (x * 1LL * y) % mod; }
int n, m, q;
vector<int> g[2005];
vector<int> pr[2005];
int maxEdge[2005];
int mem[2005][2005];
bool vis[2005][2005];
int solve(int node, int remEdges) {
  if (remEdges == 0) return node == 0 ? 0 : -1;
  if (vis[node][remEdges]) return mem[node][remEdges];
  vis[node][remEdges] = true;
  int ans = -1;
  for (int i = 0; i < int(g[node].size()); i++) {
    int child = g[node][i], price = pr[node][i];
    int tmp = solve(child, remEdges - 1);
    if (tmp == -1) continue;
    ans = max(ans, tmp + price);
  }
  return mem[node][remEdges] = ans;
}
int getSum(int x, int y) {
  int a = x + y, b = y - x + 1;
  if (a % 2 == 0)
    a /= 2;
  else
    b /= 2;
  return mul(a, b);
}
vector<pair<int, int> > M;
pair<int, int> arr[40005];
int timeToBeBetter[40005];
int ind, sz;
int get(pair<int, pair<int, int> > X, int length) {
  if (length < X.first) return -1;
  return -X.second.first - X.second.second * (length - X.first);
}
int better(pair<int, int> X, pair<int, int> Y) {
  if (X.first == Y.first) return -1;
  assert(Y.first > X.first);
  if (X.second <= Y.second) return -1;
  return (X.first - Y.first) / (Y.second - X.second) + 1;
}
void enqueue(pair<int, int> cand) {
  if (sz == 0) {
    arr[ind + (sz++)] = cand;
    return;
  }
  while (sz > 0) {
    int e = better(cand, arr[ind + sz - 1]);
    if (e == -1)
      return;
    else if (sz == 1 || e > timeToBeBetter[ind + sz - 1]) {
      arr[ind + sz] = cand;
      timeToBeBetter[ind + (sz++)] = e;
      return;
    } else {
      sz--;
    }
  }
  arr[ind + (sz++)] = cand;
  return;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m >> q;
  for (int i = 0; i < m; i++) {
    int u, v, w;
    cin >> u >> v >> w;
    --u;
    --v;
    maxEdge[u] = max(maxEdge[u], w);
    maxEdge[v] = max(maxEdge[v], w);
    g[u].push_back(v);
    g[v].push_back(u);
    pr[u].push_back(w);
    pr[v].push_back(w);
  }
  int ans = 0;
  for (int length = 1; length < n; length++) {
    int tmp = 0;
    for (int node = 0; node < n; node++) {
      int d = solve(node, length);
      if (d == -1) continue;
      tmp = max(tmp, d);
    }
    ans = add(ans, tmp % mod);
  }
  for (int node = 0; node < n; node++) {
    int d = solve(node, n);
    if (d == -1) continue;
    M.push_back(make_pair(d, maxEdge[node]));
  }
  sort(M.rbegin(), M.rend());
  for (int i = 0; i < int(M.size()); i++) enqueue(M[i]);
  for (int length = n; length <= q;) {
    if (sz == 1) {
      pair<int, int> cur = arr[ind];
      int new_length = q + 1;
      --sz;
      int diff = new_length - length;
      int constant = mul(cur.first, diff);
      int from = length - n, to = length + diff - 1 - n;
      ans = add(ans, add(constant, mul(getSum(from, to), cur.second)));
      length = new_length;
    } else {
      pair<int, int> cur = arr[ind];
      int new_length = n + timeToBeBetter[++ind];
      new_length = min(new_length, q + 1);
      --sz;
      int diff = new_length - length;
      int constant = mul(cur.first, diff);
      int from = length - n, to = length + diff - 1 - n;
      ans = add(ans, add(constant, mul(getSum(from, to), cur.second)));
      length = new_length;
    }
  }
  cout << ans << endl;
  return 0;
}
