#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const ll MOD = (1e+9)+7;
const ll INF = (ll)1000000007 * 1000000007;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef long double ld;
typedef complex<ld> Point;
const ld eps = 1e-11;
const ld pi = acos(-1.0);
typedef pair<ll, ll> LP;
typedef pair<ld, ld> LDP;
int par[1000];
int rank1[1000];
void init(int n) {
	for (int i = 0; i < n; i++) {
		par[i] = i;
		rank1[i] = 0;
	}
}
int find1(int x) {
	if (par[x] == x) {
		return x;
	}
	else {
		return par[x] = find1(par[x]);
	}
}
void unite1(int x, int y) {
	x = find1(x);
	y = find1(y);
	if (x == y)return;
	if (rank1[x] < rank1[y]) {
		par[x] = y;
	}
	else {
		par[y] = x;
		if (rank1[x] == rank1[y])rank1[x]++;
	}
}
bool same(int x, int y) {
	return find1(x) == find1(y);
}
struct edge { int u, v;ll cost; };
bool comp(const edge&e1, const edge&e2) {
	return e1.cost < e2.cost;
}
edge es[2000];
int V, E;
int used[2000] = {};
ll kruskal() {
	init(V);
	ll res = 0;
	for (int i = 0; i < E; i++) {
		edge e = es[i];
		if (!same(e.u, e.v)) {
			unite1(e.u, e.v);
			res += e.cost;
			used[i] = 1;
		}
	}
	return res;
}
ll mod_pow(ll x, ll n) {
	ll res = 1;
	while (n > 0) {
		if (n & 1) res = res * x%MOD;
		x = x * x%MOD;
		n >>= 1;
	}
	return res;
}
ll x;
struct edge2 { int to; ll cost; };
vector<edge2> G[1000];
map<P, int> trans;
int main() {
	cin >> V >> E >> x;
	rep(i, E) {
		int u, v; ll w;
		cin >> u >> v >> w; u--; v--;
		es[i] = { u,v,w };
	}
	sort(es, es + E ,comp);
	rep(i, E) {
		int u = es[i].u; int v = es[i].v; ll w = es[i].cost;
		G[u].push_back({ v,w });
		trans[{u, v}] = trans[{v, u}] = i;
		G[v].push_back({ u,w });
	}
	ll sum = kruskal();
	int eq = 0; int up = 0;
	rep(i, E) {
		if (used[i])continue;
		int fr = es[i].v;int to = es[i].u;
		int used2[1000] = {}; used2[fr] = 1;
		queue<pair<int,ll>> q;
		q.push({ fr,0 });
		ll ma; bool aa = false;
		while (!q.empty()) {
			pair<int, ll> now = q.front(); q.pop();
			int g = now.first; ll s = now.second;
			int len = G[g].size();
			rep(j, len) {
				int nev = G[g][j].to; ll co = G[g][j].cost;
				if (used2[nev])continue;
				if (!used[trans[{g, nev}]])continue;
				if (nev == to) {
					ma = max(co, s); aa = true; break;
				}
				else {
					used2[nev] = 1;
					q.push({ nev,max(co,s) });
				}
			}
			if (aa)break;
		}
		ll dif = es[i].cost - ma;
		if (dif == x - sum)eq++;
		else if (dif > x - sum)up++;
	}
	if (x < sum) {
		cout << 0 << endl;
	}
	else if (x > sum) {
		ll out = mod_pow(2, eq); (out += MOD - 1) %= MOD;
		(out *= mod_pow(2, up+1)) %= MOD;
		cout << out%MOD << endl;
	}
	else {
		ll out = mod_pow(2, eq); (out += MOD - 1) %= MOD;
		(out *= mod_pow(2, up + 1)) %= MOD;
		ll out2 = mod_pow(2, V - 1); (out2 += MOD - 2) % MOD;
		(out2 *= mod_pow(2, E - V + 1)) %= MOD;
		cout << (out + out2) % MOD << endl;
	}
	return 0;
}

Measured memory_bytes: 768