#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
using ld = long double;
using P = pair<int, int>;
using vs = vector<string>;
using vi = vector<int>;
using vvi = vector<vi>;
template <class T>
using PQ = priority_queue<T>;
template <class T>
using PQG = priority_queue<T, vector<T>, greater<T>>;
const int INF = 0xccccccc;
const ll LINF = 0xcccccccccccccccLL;
template <typename T1, typename T2>
inline bool chmax(T1 &a, T2 b) {
  return a < b && (a = b, true);
}
template <typename T1, typename T2>
inline bool chmin(T1 &a, T2 b) {
  return a > b && (a = b, true);
}
template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
  return is >> p.first >> p.second;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  return os << p.first << ' ' << p.second;
}
const unsigned int mod = 1000000007;
struct mint {
  unsigned int x;
  mint() : x(0) {}
  mint(int64_t x_) {
    int64_t v = int64_t(x_ % mod);
    if (v < 0) v += mod;
    x = (unsigned int)v;
  }
  static mint row(int v) {
    mint v_;
    v_.x = v;
    return v_;
  }
  mint operator-() const { return mint(-int64_t(x)); }
  mint &operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint &operator-=(const mint a) {
    if ((x += mod - a.x) >= mod) x -= mod;
    return *this;
  }
  mint &operator*=(const mint a) {
    uint64_t z = x;
    z *= a.x;
    x = (unsigned int)(z % mod);
    return *this;
  }
  mint operator+(const mint a) const { return mint(*this) += a; }
  mint operator-(const mint a) const { return mint(*this) -= a; }
  mint operator*(const mint a) const { return mint(*this) *= a; }
  friend bool operator==(const mint &a, const mint &b) { return a.x == b.x; }
  friend bool operator!=(const mint &a, const mint &b) { return a.x != b.x; }
  mint &operator++() {
    x++;
    if (x == mod) x = 0;
    return *this;
  }
  mint &operator--() {
    if (x == 0) x = mod;
    x--;
    return *this;
  }
  mint operator++(int) {
    mint result = *this;
    ++*this;
    return result;
  }
  mint operator--(int) {
    mint result = *this;
    --*this;
    return result;
  }
  mint pow(int64_t t) const {
    mint x_ = *this, r = 1;
    while (t) {
      if (t & 1) r *= x_;
      x_ *= x_;
      t >>= 1;
    }
    return r;
  }
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint a) { return *this *= a.inv(); }
  mint operator/(const mint a) { return mint(*this) /= a; }
};
istream &operator>>(istream &is, mint &a) { return is >> a.x; }
ostream &operator<<(ostream &os, const mint &a) { return os << a.x; }
string to_string(mint a) { return to_string(a.x); }
struct edge {
  int to, weigh;
};
bool comp(const P &a, const P &b) { return a.second > b.second; }
mint calc(int &ft, int et, ll f, ll p) {
  ll fv = f + p * ft + p;
  ll ev = f + p * et;
  int z = ft;
  ft = et;
  return mint(fv + ev) * (et - z) * ((mod + 1) >> 1);
}
mint ans;
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m, q;
  cin >> n >> m >> q;
  vector<vector<edge>> G(n);
  for (int i = 0; i < m; ++i) {
    int u, v, w;
    cin >> u >> v >> w;
    u--;
    v--;
    G[u].push_back((edge){v, w});
    G[v].push_back((edge){u, w});
  }
  vector<vector<ll>> dist(m + 1, vector<ll>(n, -LINF));
  dist[0][0] = 0;
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
      for (edge &e : G[j]) {
        int ne = e.to;
        chmax(dist[i + 1][ne], dist[i][j] + e.weigh);
      }
    }
  }
  for (int i = 0; i < m; ++i) {
    ans += *max_element(dist[i + 1].begin(), dist[i + 1].end());
  }
  deque<tuple<ll, int, ll>> dq;
  vector<pair<ll, int>> shoki(n);
  for (int i = 0; i < n; ++i) {
    int w = 0;
    for (edge &e : G[i]) chmax(w, e.weigh);
    shoki[i] = {dist[m][i], w};
  }
  sort(shoki.begin(), shoki.end(), comp);
  for (int i = 0; i < n; ++i) {
    if (dq.empty()) {
      dq.emplace_back(shoki[i].first, shoki[i].second, LINF);
      continue;
    }
    if (get<0>(dq.front()) >= shoki[i].first) continue;
    while (!dq.empty() and get<1>(dq.front()) == shoki[i].second)
      dq.pop_front();
    ll tim = LINF;
    while (!dq.empty()) {
      auto [f, p, t] = dq.front();
      tim = (shoki[i].first - f) / (p - shoki[i].second);
      if (tim >= t)
        dq.pop_front();
      else
        break;
    }
    dq.emplace_front(shoki[i].first, shoki[i].second, tim);
  }
  int nt = 0;
  q -= m;
  while (!dq.empty()) {
    auto [f, p, t] = dq.front();
    dq.pop_front();
    ans += calc(nt, min(t, ll(q)), f, p);
  }
  cout << ans << endl;
}
