#include <bits/stdc++.h>
 
#define rep(i, n)      for (int i = 0; i < (n); i++)
#define repr(i, n)     for (int i = (n) - 1; i >= 0; i--)
#define repe(i, l, r)  for (int i = (l); i < (r); i++)
#define reper(i, l, r) for (int i = (r) - 1; i >= (l); i--)
#define repi(i, l, r)  for (int i = (l); i <= (r); i++)
#define repir(i, l, r) for (int i = (r); i >= (l); i--)
#define range(a) a.begin(), a.end()
void init_io() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); std::cout << std::fixed << std::setprecision(15); }
 
using namespace std;
using ll = long long;

struct edge {
  int u, v; ll w; ll d;
};

struct unionfind {
  vector<int> dat;

  unionfind(int n) : dat(n, -1) {}

  int find(int x) {
    if (dat[x] < 0) return x;
    return dat[x] = find(dat[x]);
  }

  bool unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return false;
    if (dat[x] > dat[y]) swap(x, y);
    dat[x] += dat[y];
    dat[y] = x;
    return true;
  }

  int size(int x) {
    return -dat[find(x)];
  }
};

constexpr int MOD = 1000000007;

class mint {
  int n;
public:
  mint(int n_ = 0) : n(n_) {}
  explicit operator int() { return n; }
  friend mint operator-(mint a) { return -a.n + MOD * (a.n != 0); }
  friend mint operator+(mint a, mint b) { int x = a.n + b.n; return x - (x >= MOD) * MOD; }
  friend mint operator-(mint a, mint b) { int x = a.n - b.n; return x + (x < 0) * MOD; }
  friend mint operator*(mint a, mint b) { return (long long)a.n * b.n % MOD; }
  friend mint &operator+=(mint &a, mint b) { return a = a + b; }
  friend mint &operator-=(mint &a, mint b) { return a = a - b; }
  friend mint &operator*=(mint &a, mint b) { return a = a * b; }
  friend bool operator==(mint a, mint b) { return a.n == b.n; }
  friend bool operator!=(mint a, mint b) { return a.n != b.n; }
  friend istream &operator>>(istream &i, mint &a) { return i >> a.n; }
  friend ostream &operator<<(ostream &o, mint a) { return o << a.n; }
};
mint operator "" _m(unsigned long long n) { return n; }

mint modpow(mint a, long long b) {
  mint res = 1;
  while (b > 0) {
    if (b & 1) res *= a;
    a *= a;
    b >>= 1;
  }
  return res;
}

int main() { init_io();
  int N, M; cin >> N >> M;
  ll X; cin >> X;
  vector<edge> E(M);
  rep(i, M) { cin >> E[i].u >> E[i].v >> E[i].w;
    E[i].u--;
    E[i].v--;
  }
  sort(range(E), [](edge a, edge b) { return a.w < b.w; });
  unionfind uf(N);
  ll sum = 0;
  vector<vector<pair<int, ll>>> T(N);
  vector<edge> notT;
  rep(i, M) {
    if (uf.unite(E[i].u, E[i].v)) {
      sum += E[i].w;
      T[E[i].u].emplace_back(E[i].v, E[i].w);
      T[E[i].v].emplace_back(E[i].u, E[i].w);
    } else {
      notT.push_back(E[i]);
    }
  }
  mint ans;
  if (sum == X) {
    ans += (modpow(2, N - 1) - 2) * modpow(2, M - (N - 1));
  }
  auto dfs = [&](auto dfs, int u, int v, int p) -> ll {
    if (u == v) return LLONG_MIN;
    for (auto e : T[u]) if (e.first != p) {
      ll res = dfs(dfs, e.first, v, u);
      if (res != LLONG_MAX) return max(res, e.second);
    };
    return LLONG_MAX;
  };
  rep(i, notT.size()) {
    notT[i].d = notT[i].w - dfs(dfs, notT[i].u, notT[i].v, -1);
  }
  sort(range(notT), [&](edge a, edge b) { return a.d < b.d; });
  rep(i, notT.size()) {
    if (sum + notT[i].d == X) {
      ans += modpow(2, notT.size() - (i + 1)) * 2;
    }
  }
  cout << ans << endl;
}


Measured memory_bytes: 512