#include <iostream>
#include <vector>
#include <string.h>
#include <set>
#include <map>
#include <unordered_map>
#include <assert.h>
#include <algorithm>
#include <queue>
#include <bitset>
#include <stack>
#include <chrono>
#include <random>
#define all(x) x.begin(),x.end()
#define ff first
#define ss second
#define ll long long
#define INF 1000000000000000000
#define MOD 1000000007
#define rnd mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define FIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define uid uniform_int_distribution <int>
using namespace std;
// Read the question carefully and see all the given sample tests
// Think about the correctness before implementing

using PII = pair<int, int>;
const int N = 2005;
const int LOG = 12;
vector <PII> v[N];
vector <int> id(N);
vector <int> lvl(N);
vector <vector<int>> pr;
void init() {
	for (int i = 0; i < N; i++) {
		id[i] = i;
	}
}
int root(int x) {
	if(id[x] == x)
		return x;
	return id[x] = root(id[x]);
}
void union1(int x, int y) {
	int p = root(x);
	int q = root(y);
	id[p] = q;
}
int lca(int x, int y) {
	if(lvl[x] < lvl[y])
		swap(x, y);
	for (int i = LOG - 1; i >= 0; i--) {
		if(pr[x][i] != -1 && lvl[pr[x][i]] >= lvl[y]) {
			x = pr[x][i];
		}
	}
	if(x == y)
		return y;
	for (int i = LOG - 1; i >= 0; i--) {
		if(pr[x][i] != pr[y][i]) {
			x = pr[x][i];
			y = pr[y][i];
		}
	}
	return pr[x][0];
}
void dfs(int s, int par, int c) {
	lvl[s] = c;
	for (auto g : v[s]) {
		if(g.ff != par) {
			dfs(g.ff, s, c + 1);
			pr[g.ff][0] = s;
		}
	}
}
void pre() {
	for (int j = 1; j < LOG; j++) {
		for (int i = 1; i < N; i++) {
			if(pr[i][j - 1] != -1) {
				pr[i][j] = pr[pr[i][j - 1]][j - 1];
			}
		}
	}
}
vector <vector<int>> A(N, vector<int>(N));
int calc_max(int x, int y) {
	int mx = 0;
	int lc = lca(x, y);
	while(x != lc) {
		mx = max(mx, A[x][pr[x][0]]);
		x = pr[x][0];
	}
	while(y != lc) {
		mx = max(mx, A[y][pr[y][0]]);
		y = pr[y][0];
	}
	return mx;
}
int main() {
	int n, m;
	cin >> n >> m;
	ll X;
	cin >> X;
	pair <int, pair<int, int>> edg[m];
	for (int i = 0; i < m; i++) {
		int x, y, w;
		cin >> x >> y >> w;
		edg[i] = {w, {x, y}};
	}
	sort(edg, edg + m);
	ll sum = 0;
	int cnt = 0;
	vector <bool> mark(m);
	init();
	for (int i = 0; i < m; i++) {
		int x, y, w;
		w = edg[i].ff, x = edg[i].ss.ff, y = edg[i].ss.ss;
		if(root(x) != root(y)) {
			union1(x, y);
			v[x].push_back({y, w});
			v[y].push_back({x, w});
			A[x][y] = w;
			A[y][x] = w;
			sum += w;
			cnt++;
			mark[i] = true;
		}
	}
	pr.assign(N, vector<int>(LOG, -1));
	dfs(1, -1, 0);
	pre();
	int c = 0, gr = 0;
	for (int i = 0; i < m; i++) {
		if(mark[i])
			continue;
		int x, y, w;
		w = edg[i].ff, x = edg[i].ss.ff, y = edg[i].ss.ss;
		int val = calc_max(x, y);
		if(sum - val + w == X) {
			c++;
		}
		else if(sum - val + w > X) {
			gr++;
		}
	}
 	vector <ll> pw2(N);
	pw2[0] = 1;
	for (int i = 1; i < N; i++) {
		pw2[i] = (pw2[i - 1] * 2) % MOD;
	}
	if(sum != X && c == 0) {
		cout << 0;
	}
	else {
		ll ans = 1;
		if(sum == X) {
			c += cnt;
			ans = (pw2[c] - 2 + MOD) % MOD;
			ans = (ans * pw2[gr]) % MOD;
			cout << ans;
		}
		else {
			ans = (pw2[c + 1] - 2 + MOD) % MOD;
			ans = (ans * pw2[gr]) % MOD;
			cout << ans;
		}
	}
}


Measured memory_bytes: 16384