#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define FILL(a, n, x) memset((a), (x), sizeof ((a)[0]) * (n))
#define COPY(a, n, b) memcpy((b), (a), sizeof ((a)[0]) * (n))
using namespace std;

const int mod = 1e9 + 7;
typedef long long li;

inline int Add(int x) { return x >= mod ? x - mod : x; }
inline void Add(int &x, int y) { x += y; if (x >= mod) x -= mod; }
inline int Sub(int x) { return x < 0 ? x + mod : x; }
inline void Sub(int &x, int y) { x -= y; if (x < 0) x += mod; }
inline int Mul(int x, int y) { return (int)((li)x * y % mod); }
inline int Mul(int x, int y, int z) { return Mul(x, Mul(y, z)); }

int Pow(int x, int y) {
  int z = 1;
  for (; y; y >>= 1) {
    if (y & 1) z = Mul(z, x);
    x = Mul(x, x);
  }
  return z;
}

int Inv(int x) {
  return Pow(x, mod - 2);
}

// ----------------------------------------

inline void Max(int &x, int y) {
  if (y > x) x = y;
}

typedef pair<int, int> pii;

const int maxn = 1e5;
const int maxlgn = 20;

int n, m;
li X;

struct Edge {
  int u, v, w;
  bool operator < (const Edge &b) const {
    return w < b.w;
  }
} edge[maxn];

bool is_in[maxn];
vector<pii> T[maxn];
int par[maxn];

void InitDsu(void) {
  for (int i = 0; i < n; ++i) {
    par[i] = i;
  }
}

int Find(int x) {
  while (x != par[x]) {
    par[x] = par[par[x]];
    x = par[x];
  }
  return x;
}

void Unite(int x, int y) {
  par[Find(x)] = Find(y);
}

bool Same(int x, int y) {
  return Find(x) == Find(y);
}

int anc[maxn][maxlgn];
int maxw[maxn][maxlgn];
int dep[maxn];

void Dfs1(int u, int p, int w, int d) {
  anc[u][0] = p;
  maxw[u][0] = w;
  dep[u] = d;
  for (int j = 1; j < maxlgn; ++j) {
    int mid = anc[u][j - 1];
    if (mid == -1) {
      anc[u][j] = -1;
      maxw[u][j] = 0;
    } else {
      anc[u][j] = anc[mid][j - 1];
      maxw[u][j] = max(maxw[u][j - 1], maxw[mid][j - 1]);
    }
  }

  for (pii e : T[u]) {
    int v = e.first, ww = e.second;
    if (v != p) {
      Dfs1(v, u, ww, d + 1);
    }
  }
}

void InitLca(void) {
  Dfs1(0, -1, 0, 0);
}

int GetMax(int u, int v) {
  if (dep[u] < dep[v]) {
    swap(u, v);
  }
  int ans = 0;
  for (int j = 0; dep[u] > dep[v]; ++j) {
    if (dep[u] - dep[v] >> j & 1) {
      Max(ans, maxw[u][j]);
      u = anc[u][j];
    }
  }
  if (u == v) {
    return ans;
  }

  for (int j = maxlgn - 1; j >= 0; --j) {
    if (anc[u][j] != anc[v][j]) {
      Max(ans, maxw[u][j]);
      u = anc[u][j];
      Max(ans, maxw[v][j]);
      v = anc[v][j];
    }
  }
  Max(ans, maxw[u][0]);
  Max(ans, maxw[v][0]);
  return ans;
}

int main(void) {
  scanf("%d%d%lld", &n, &m, &X);
  for (int i = 0; i < m; ++i) {
    int u, v, w;
    scanf("%d%d%d", &u, &v, &w);
    --u; --v;
    edge[i] = {u, v, w};
  }

  sort(edge, edge + m);
  InitDsu();
  li S = 0;
  for (int i = 0; i < m; ++i) {
    int x = edge[i].u, y = edge[i].v, w = edge[i].w;
    if (!Same(x, y)) {
      Unite(x, y);
      T[x].push_back({y, w});
      T[y].push_back({x, w});
      is_in[i] = true;
      S += w;
    }
  }

  InitLca();
  int ans = 0;
  if (X == S) {
    // paint both
    Add(ans, Mul(Pow(2, m - (n - 1)), Sub(Pow(2, n - 1) - 2)));
  }
  if (X < S) {
    puts("0");
    return 0;
  }
  int less = 0, eq = 0, more = 0;
  for (int i = 0; i < m; ++i) {
    if (!is_in[i]) {
      li val = edge[i].w - GetMax(edge[i].u, edge[i].v) + S;
      if (val < X) ++less; else if (val == X) ++eq; else ++more;
    }
  }
  Add(ans, Mul(2, Pow(2, more), Sub(Pow(2, eq) - 1)));
  printf("%d\n", ans);
  return 0;
}


Measured memory_bytes: 6912