#include <bits/stdc++.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=int(a)-1;i>=int(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)

#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define getidx(ary,key) lower_bound(_all(ary),key)-begin(ary)
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))
#define popcount(n) (__builtin_popcountll(n))

using namespace std;

template<class T>bool chmax(T &a, const T &b) { return (a < b) ? (a = b, 1) : 0;}
template<class T>bool chmin(T &a, const T &b) { return (b < a) ? (a = b, 1) : 0;}

using ll = long long;
using R = long double;
const R EPS = 1e-9L; // [-1000,1000]->EPS=1e-8 [-10000,10000]->EPS=1e-7
inline int sgn(const R& r) {return (r > EPS) - (r < -EPS);}
inline R sq(R x) {return sqrt(max(x, 0.0L));}

const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

// Problem Specific Parameter:

using state = tuple<ll, int, int>;
vector<state> ary;
bool used[2010];

// Description: 素集合を管理するデータ構造
// TimeComplexity: 初期化$\mathcal{O}(n)$ 更新$\mathcal{O}(\log n)$
// Verifyed: AOJ DSL_1_A

struct Union_find {
	Union_find(int n) {data.assign(n, -1);}
	int find(int x) {return (data[x] < 0) ? x : data[x] = find(data[x]);}
	void unite(int a, int b) {
		a = find(a), b = find(b);
		if (a != b) {
			if (data[a] < data[b]) swap(a, b);
			data[a] += data[b], data[b] = a;
		}
	}
	bool same(int a, int b) {return find(a) == find(b);}
	int size(int x) {return -data[x];}
	vector<int> data;
};

const ll inf = 1LL << 30;
using edge = struct {int to; ll cost;};
const int limit = 2010;
vector<edge> graph[limit];

ll dfs(int v, int p, int t, ll cur) {
	if (v == t) return cur;
	ll ret = -inf;
	for (auto &e : graph[v]) {
		if (e.to == p) continue;
		chmax(ret, dfs(e.to, v, t, max(cur, e.cost)));
	}
	return ret;
}

const ll mod = 1000000007LL;
ll two[limit];


int main(void) {
	two[0] = 1LL;
	rep(i, 1, limit) two[i] = 2LL * two[i - 1] % mod;

	int n, m;
	cin >> n >> m;

	ll x;
	cin >> x;

	rep(i, m) {
		int u, v, w;
		cin >> u >> v >> w;
		u--, v--;
		ary.push_back(state(w, u, v));
	}

	sort(begin(ary), end(ary));

	ll cur = 0LL;

	Union_find uf(n);
	int comp = n;

	rep(idx, m) {
		int u, v; ll w;
		tie(w, u, v) = ary[idx];
		if (uf.same(u, v)) continue;
		comp--, cur += w;
		used[idx] = true;
		graph[u].push_back({v, w});
		graph[v].push_back({u, w});
		uf.unite(u, v);
		if (comp == 1) break;
	}


	ll ans = 0LL;
	if (cur == x) {
		ll add = (two[n - 1] + mod - 2LL) % mod;
		add = 1LL * add * two[m - n + 1] % mod;
		ans = (ans + add) % mod;
	}

	vector<ll> cand;

	rep(i, m) {
		if (used[i]) continue;
		int u, v; ll w;
		tie(w, u, v) = ary[i];
		ll alt = cur - dfs(u, -1, v, 0LL) + w;
		cand.push_back(alt);
	}

	sort(begin(cand), end(cand));
	const int rest = m - n + 1;
	rep(i, rest) {
		if (cand[i] == x) {
			ans = (ans + two[rest - i]) % mod;
		}
	}

	cout << ans << endl;


	return 0;
}

Measured memory_bytes: 512