#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;

const long long MOD = 1000000007;
const int MAX = 1010;

long long mod_mul(long long x, long long y) {
	return (x*y) % MOD;
}
long long mod_dif(long long x,long long y){
	return (MOD + x - y) % MOD;
}

class unionfind {
private:
	int par[MAX]; int rank[MAX];
public:
	unionfind(int n) {
		for (int i = 0; i < n; i++) {
			par[i] = i;
			rank[i] = 0;
		}
	}
	int find(int x) {
		if (par[x] == x) {
			return x;
		}
		else {
			return par[x] = find(par[x]);
		}
	}
	bool same(int x, int y) {
		return find(x) == find(y);
	}
	void unite(int x, int y) {
		if (!same(x, y)) {
			x = par[x]; y = par[y];
			if (rank[x] < rank[y]) {
				par[x] = y;
			}
			else {
				par[y] = x;
				if (rank[x] == rank[y]) {
					rank[x]++;
				}
			}
		}
	}
};

struct edge
{
	int from; int to; long long value;
	bool operator<(const edge& rhs)const {
		return value < rhs.value;
	}
};

edge a[MAX * 2];
vector<edge> g[MAX];

unionfind u(MAX - 1);
long long ex_cost[MAX*2];
long long parent[MAX];

long long dfs(int start, int goal, long long cost, int n) {
	stack<int> s;
	s.push(start);
	long long max_value = 0;
	for (int i = 1; i <= n; i++) {
		parent[i] = -1;
	}
	parent[start] = 0;
	while (!s.empty()) {
		int now = s.top();
		s.pop();
		for (int i = 0; i < g[now].size(); i++) {
			int next = g[now][i].to; long long now_cost = g[now][i].value;
			if (parent[next] == -1) {
				parent[next] = max(parent[now], now_cost);
				s.push(next);
				if (next == goal) {
					return cost - parent[goal];
				}
			}
		}
	}
	return -2;
	/*
	int now = goal;
	while (now != start) {
	int next = parent[now];
	for (int i = 0; i < g[now].size(); i++) {
	if (g[now][i].to == next) {
	max_value = max(max_value, g[now][i].value);
	break;
	}
	}
	now = next;
	}
	return cost - max_value;
	*/
}

int main() {
	int n, m; long long x;
	cin >> n >> m >> x;
	for (int i = 1; i <= m; i++) {
		int t, v; long long w;
		cin >> t >> v >> w;
		a[i] = { t,v,w };
	}
	sort(a + 1, a + 1 + m);
	for (int i = 1; i <= m; i++) {
		ex_cost[i] = 0;
	}
	long long min_value = 0;
	for (int i = 1; i <= m; i++) {
		edge now_edge = a[i];
		int now_point, next_point; long long now_value;
		now_point = a[i].from; next_point = a[i].to; now_value = a[i].value;
		if (!u.same(now_point, next_point)) {
			u.unite(now_point, next_point);
			g[now_point].push_back({ now_point,next_point,now_value });
			g[next_point].push_back({ next_point, now_point,now_value });
			min_value += now_value;
		}
		else {
			ex_cost[i] = dfs(now_point, next_point, now_value, n);
		}
	}

	long long ans1 = 1; long long ans2 = 1;
	if (min_value == x) {
		for (int i = 1; i <= m; i++) {
			if (ex_cost[i] == 0) {
				ans1 = mod_mul(ans1, 2);
			}
			else {
				ans2 = mod_mul(ans2, 2);
			}
		}
		cout << mod_mul(mod_dif(ans1, 2), ans2) << endl;
	}
	else if (min_value > x) {
		cout << 0 << endl;
	}
	else {
		long long white, other;
		other = white = 1;
		x -= min_value;
		for (int i = 1; i <= m; i++) {
			if (ex_cost[i] == x) {
				white = mod_mul(white, 2);
			}
			else if (ex_cost[i] > x) {
				other = mod_mul(other, 2);
			}
		}
		cout << mod_mul(mod_mul(2, mod_dif(white, 1)), other) << endl;
	}

}

Measured memory_bytes: 512