#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctype.h>
#include <algorithm>
#include <fstream>
#include <climits>
#define mp make_pair
#define Debug(...) fprintf(stdout, __VA_ARGS__)

using namespace std;

typedef long long LL;
typedef pair<int, int> pii;
typedef pair<int, LL> pil;

const int MAXN = 1e5 + 7;
const int MAXM = 2e5 + 7;
const int MOD = 1e9 + 7;
const int LogN = 17;

inline void proc_status() {
	ifstream t("/proc/self/status");
	cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>()) << endl;
}

template<typename T> inline T read() {
	T res = 0, flag = 1; char in = getchar();
	while(!isdigit(in)) { if(in == '-') flag = -1; in = getchar(); }
	while(isdigit(in)) { res = (res << 1) + (res << 3) + in - '0'; in = getchar(); }
	return res * flag;
}

template<typename T> inline void chkmax(T &a, T b) { if(a < b) a = b; }
template<typename T> inline void chkmin(T &a, T b) { if(a > b) a = b; }

struct Edge {
	int x, y, w;
	bool operator < (const Edge &t) const { return w < t.w; }
}edge[MAXM];

inline int fpm(int x, int y) {
	int res = 1;
	while(y) {
		if(y & 1) res = (LL) res * x % MOD;
		y >>= 1; x = (LL) x * x % MOD;
	}
	return res;
}

int n, m;
LL mst, K;

int dex, head[MAXN], to[MAXN << 1], nxt[MAXN << 1], w[MAXN << 1];

inline void Link(int x, int y, int val) { nxt[++dex] = head[x]; to[dex] = y; head[x] = dex; w[dex] = val; }

namespace DSU {
	int f[MAXN];
	inline void init() { for(int i = 1; i <= n; ++i) f[i] = i; }
	inline int find(int x) { return f[x] ^ x ? f[x] = find(f[x]) : x; }
	inline bool merge(int x, int y) { x = find(x); y = find(y); if(x ^ y) { f[x] = y; return 1; } return 0; }
	inline bool merge(Edge &t) { return merge(t.x, t.y); }
}

namespace Tree {
	int f[LogN][MAXN];
	int mx[LogN][MAXN];
	int dep[MAXN];

	void dfs(int u, int fa) {
		f[0][u] = fa; dep[u] = dep[fa] + 1;
		for(int i = head[u]; i; i = nxt[i]) {
			int v = to[i];
			if(v == fa) continue;
			mx[0][v] = w[i];
			dfs(v, u);
		}
	}

	inline void init() {
		dfs(1, 0);
		for(int t = 1; t < LogN; ++t) {
			for(int i = 1; i <= n; ++i) {
				f[t][i] = f[t - 1][f[t - 1][i]];
				mx[t][i] = max(mx[t - 1][i], mx[t - 1][f[t - 1][i]]);
			}
		}
	}

	inline int Query(int x, int y) {
		if(dep[x] < dep[y]) swap(x, y);
		int res = 0;
		for(int i = LogN - 1; i >= 0; --i)
			if(dep[f[i][x]] >= dep[y]) {
				chkmax(res, mx[i][x]);
				x = f[i][x];
			}
		if(x == y) return res;
		for(int i = LogN - 1; i >= 0; --i) {
			if(f[i][x] != f[i][y]) {
				chkmax(res, mx[i][x]);
				chkmax(res, mx[i][y]);
				x = f[i][x];
				y = f[i][y];
			}
		}
		return max(res, max(mx[0][x], mx[0][y]));
	}
}

int vis[MAXM];

inline void init() {
	n = read<int>(); m = read<int>(); K = read<LL>();
	for(int i = 1; i <= m; ++i) {
		edge[i].x = read<int>();
		edge[i].y = read<int>();
		edge[i].w = read<int>();
	}
	sort(edge + 1, edge + m + 1);
	DSU::init();
	for(int i = 1; i <= m; ++i)
		if(DSU::merge(edge[i])) {
			mst += edge[i].w;
			Link(edge[i].x, edge[i].y, edge[i].w);
			Link(edge[i].y, edge[i].x, edge[i].w);
//		cout << edge[i].x << ' ' << edge[i].y << ' ' << edge[i].w<< endl;// ' ' << Tree::Query(edge[i].x, edge[i].y) << endl;
			vis[i] = 1;
		}
	Tree::init();
//	cout << mst << endl;
}

inline int calc(LL x) {
	if(x <= mst) return fpm(2, m) - 1;
	int cnt = n - 1;
	for(int i = 1; i <= m; ++i) if(!vis[i]) {
//		cout << edge[i].x << ' ' << edge[i].y << ' ' << Tree::Query(edge[i].x, edge[i].y) << endl;
		if(mst - Tree::Query(edge[i].x, edge[i].y) + edge[i].w < x) {
			++cnt;
		}
	}
//	cout << cnt << endl;
	return fpm(2, m - cnt + 1) - 1;
}

inline void solve() {
//cout << calc(K) << endl;
//cout << calc(K + 1) << endl;
//exit(0);
	printf("%d\n", (calc(K) - calc(K + 1) + MOD) % MOD);
}

inline void clar() {
	memset(vis, 0, sizeof vis);
	memset(head, 0, sizeof head);
	dex = 0; mst = 0;
}

int main() {
	int T = 1;//read<int>();
	while(T--) {
		init();
		solve();
		clar();
	}

	return 0;
}



Measured memory_bytes: 17408