#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <fstream>
#include <cassert>
#include <cstring>
#include <unordered_set>
#include <unordered_map>
#include <numeric>
#include <ctime>
#include <bitset>
#include <complex>
#include <chrono>
#include <random>
#include <functional>

using namespace std;

typedef long long ll;

#define int ll

const int N = 1e3 + 7;
const int K = 22;
const int MOD = 1e9 + 7;

int add(int a, int b) {
	return (a + b) % MOD;
}

int mul(int a, int b) {
	return ((ll)a * b) % MOD;
}

int binpow(int a, int b) {
	int res = 1;
	while (b) {
		if (b & 1) res = mul(res, a);
		a = mul(a, a);
		b >>= 1;
	}
	return res;
}

struct Dsu {
	vector<int> p;
	vector<int> rank;

	int get(int v) {
		if (p[v] != v) {
			p[v] = get(p[v]);
		}
		return p[v];
	}

	void merge(int u, int v) {
		u = get(u);
		v = get(v);
		if (u == v) return;
		if (rank[u] < rank[v]) swap(u, v);
		p[v] = u;
		if (rank[u] == rank[v]) rank[u]++;
	}

	int same(int u, int v) {
		return get(u) == get(v);
	}

	Dsu(int n) {
		p.resize(n);
		iota(p.begin(), p.end(), 0);
		rank.resize(n);
	} 
};

struct Edge {
	int u, v, w;

	Edge() {}

	Edge(int u_, int v_, int w_) {
		u = u_;
		v = v_;
		w = w_;
	}

	bool operator<(const Edge &other) const {
		return w < other.w;
	}
};

int n;

int timer = 0;

int h[N];
int p[N];
int val[N];
int tin[N];
int tout[N];
int up[K][N];
int mx[K][N];
vector<pair<int, int>> g[N];

void dfs(int cur, int pr, int ch, int vl) {
	h[cur] = ch;
	p[cur] = pr;
	val[cur] = vl;
	tin[cur] = timer++;
	for (auto t : g[cur]) {
		if (t.first != p[cur]) {
			dfs(t.first, cur, ch + 1, t.second);
		}
	}
	tout[cur] = timer++;
}

void init() {
	dfs(0, -1, 0, -1);
	for (int i = 0; i < n; i++) {
		up[0][i] = p[i];
		mx[0][i] = val[i];
	}
	for (int i = 0; i + 1 < K; i++) {
		for (int j = 0; j < n; j++) {
			int mid = up[i][j];
			if (mid == -1) {
				up[i + 1][j] = -1;
			} else {
				up[i + 1][j] = up[i][mid];
				mx[i + 1][j] = max(mx[i][j], mx[i][mid]);
			}
		}
	}
}

int anc(int a, int b) {
	return tin[a] <= tin[b] && tout[b] <= tout[a];
}

int lca(int a, int b) {
	if (anc(a, b)) {
		return a;
	} else if (anc(b, a)) {
		return b;
	} else {
		for (int i = K - 1; i >= 0; i--) {
			if (up[i][a] != -1 && !anc(up[i][a], b)) {
				a = up[i][a];
			}
		}
		return p[a];
	}
}

int gmx(int v, int dh) {
	int ans = -1;
	for (int i = 0; i < K; i++) {
		if ((dh >> i) & 1) {
			ans = max(ans, mx[i][v]);
			v = up[i][v];
		}
	}
	return ans;
}

int mxp(int u, int v) {
	int l = lca(u, v);
	return max(gmx(u, h[u] - h[l]), gmx(v, h[v] - h[l]));
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);	

	int m, x;
	cin >> n >> m >> x;
	vector<Edge> ed;
	for (int i = 0; i < m; i++) {
		int u, v, w;
		cin >> u >> v >> w;
		u--;
		v--;
		ed.push_back(Edge(u, v, w));
	}
	sort(ed.begin(), ed.end());
	Dsu d(n);
	for (auto t : ed) {
		if (!d.same(t.u, t.v)) {
			d.merge(t.u, t.v);
			g[t.u].push_back({t.v, t.w});
			g[t.v].push_back({t.u, t.w});
			x -= t.w;
		}
	}
	init();
	auto gv = [&](const Edge &a) {
		return a.w - mxp(a.u, a.v);
	};
	sort(ed.begin(), ed.end(), [&](const Edge &a, const Edge &b) {
		return gv(a) < gv(b);
	});
	int ans = 0;
	for (int i = 1; i < m; i++) {
		if (gv(ed[i]) == x) {
			ans = add(ans, binpow(2, m - 1 - i));
		}
	}
	ans = mul(ans, 2);
	cout << ans << endl;
}


Measured memory_bytes: 768