#include <bits/stdc++.h>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define sz(x) static_cast<int>((x).size())

using LL = long long;
template<class T, size_t D>
struct vec : vector<vec<T, D - 1>> {
  template<class... Args>
  vec(size_t n = 0, Args... args)
    : vector<vec<T, D - 1>>(n, vec<T, D - 1>(args...)) {}
};
template<class T>
struct vec<T, 1> : vector<T> {
  template<class... Args>
  vec(Args... args)
    : vector<T>(args...) {}
};

template<class T>
inline bool asMn(T& a, const T& b) { return a > b ? a = b, true : false; }
template<class T>
inline bool asMx(T& a, const T& b) { return a < b ? a = b, true : false; }
inline int nex(int i, int n) { return i == n - 1 ? 0 : i + 1; }
inline int pre(int i, int n) { return !i ? n - 1 : i - 1; }

const int MOD = 1e9 + 7;
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());

struct DSU {
  int nSet;
  vec<int, 1> par, car;
  DSU(int nSet_)
    : nSet(nSet_) {
    par = vec<int, 1>(nSet); iota(all(par), 0);
    car = vec<int, 1>(nSet, 1);
  }

  int findPar(int i) {
    return i == par[i] ? i : par[i] = findPar(par[i]);
  }
  bool unite(int i, int j) {
    i = findPar(i); j = findPar(j);
    if (i == j) {
      return false;
    }
    if (car[i] > car[j]) {
      swap(i, j);
    }
    --nSet;
    par[i] = j;
    car[j] += car[i];
    return true;
  }
};

struct Tree {
  int n;
  vec<pair<int, int>, 2> adjEdge;
  Tree(int n_)
    : n(n_) {
    adjEdge = vec<pair<int, int>, 2>(n);
  }

  void addEdge(int i, int j, int w) {
    adjEdge[i].emplace_back(j, w);
    adjEdge[j].emplace_back(i, w);
  }

  vec<int, 1> dep;
  vec<int, 2> par, mx;
  void cal() {
    dep = vec<int, 1>(n);
    par = vec<int, 2>(__lg(n) + 1, n, -1);
    mx = vec<int, 2>(__lg(n) + 1, n);
    function<void(int)> dfs = [&](int u) {
      for (int i = 1; i < sz(par); ++i) {
        if (~par[i - 1][u]) {
          par[i][u] = par[i - 1][par[i - 1][u]];
          mx[i][u] = max(mx[i - 1][u], mx[i - 1][par[i - 1][u]]);
        }
      }

      for (auto& i : adjEdge[u]) {
        if (i.first != par[0][u]) {
          dep[i.first] = dep[u] + 1;
          par[0][i.first] = u;
          mx[0][i.first] = i.second;
          dfs(i.first);
        }
      }
    };
    dfs(0);
  }

  int getLca(int u, int v) {
    if (dep[u] > dep[v]) {
      swap(u, v);
    }
    for (int i = sz(par) - 1; ~i; --i) {
      if (dep[v] - (1 << i) >= dep[u]) {
        v = par[i][v];
      }
    }
    for (int i = sz(par) - 1; ~i; --i) {
      if (par[i][u] != par[i][v]) {
        u = par[i][u];
        v = par[i][v];
      }
    }
    return u == v ? u : par[0][u];
  }

  int getMx(int u, int dist) {
    int ret = 0;
    for (int i = 0; i < sz(par); ++i) {
      if (dist >> i & 1) {
        asMx(ret, mx[i][u]);
        u = par[i][u];
      }
    }
    return ret;
  }
};

int main() {
  ios_base::sync_with_stdio(0); cin.tie(0);

  int n, m; cin >> n >> m;
  LL x; cin >> x;
  vec<tuple<int, int, int>, 1> edge(m);
  for (auto& i : edge) {
    cin >> get<1>(i) >> get<2>(i) >> get<0>(i);
    --get<1>(i); --get<2>(i);
  }
  sort(all(edge));

  auto solve = [&](LL lim) {
    DSU dsuEdge(m);
    for (int root = 0; root < m; ++root) {
      Tree tree(n);
      DSU dsuVer(n);
      dsuVer.unite(get<1>(edge[root]), get<2>(edge[root]));
      tree.addEdge(get<1>(edge[root]), get<2>(edge[root]), 0);
      LL sumW = get<0>(edge[root]);
      for (int i = 0; i < m; ++i) {
        if (dsuVer.unite(get<1>(edge[i]), get<2>(edge[i]))) {
          tree.addEdge(get<1>(edge[i]), get<2>(edge[i]), get<0>(edge[i]));
          sumW += get<0>(edge[i]);
        }
      }

      if (sumW >= lim) {
        continue ;
      }

      tree.cal();
      for (int i = root + 1; i < m; ++i) {
        int u = get<1>(edge[i]), v = get<2>(edge[i]), w = get<0>(edge[i]), lca = tree.getLca(u, v);
        if (sumW + w - max(tree.getMx(u, tree.dep[u] - tree.dep[lca]), tree.getMx(v, tree.dep[v] - tree.dep[lca])) < lim) {
          dsuEdge.unite(root, i);
        }
      }
    }

    int ret = 1;
    for (int i = 0; i < dsuEdge.nSet; ++i) {
      ret <<= 1;
      if (ret >= MOD) {
        ret -= MOD;
      }
    }
    ret -= 2;
    if (ret < 0) {
      ret += MOD;
    }
    return ret;
  };

  int ans = solve(x) - solve(x + 1);
  if (ans < 0) {
    ans += MOD;
  }
  cout << ans << '\n';

  return 0;
}

Measured memory_bytes: 3876