#include "bits/stdc++.h"

#define REP(i,n) for(ll i=0;i<ll(n);++i)
#define RREP(i,n) for(ll i=ll(n)-1;i>=0;--i)
#define FOR(i,m,n) for(ll i=m;i<ll(n);++i)
#define RFOR(i,m,n) for(ll i=ll(n)-1;i>=ll(m);--i)
#define ALL(v) (v).begin(),(v).end()
#define UNIQUE(v) v.erase(unique(ALL(v)),v.end());
#define DUMP(v) REP(aa, (v).size()) { cout << v[aa]; if (aa != v.size() - 1)cout << " "; else cout << endl; }
#define INF 1000000001ll
#define MOD 1000000007ll
#define EPS 1e-9

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


using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll max(ll a, int b) { return max(a, ll(b)); }
ll max(int a, ll b) { return max(ll(a), b); }
ll min(ll a, int b) { return min(a, ll(b)); }
ll min(int a, ll b) { return min(ll(a), b); }

struct Edge {
	int from; int to; ll weight, num;
	bool operator<(const Edge &b)const {
		return this->weight > b.weight;
	}
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef pair<ll, int> P;
int n, m;

struct UnionFind {
	vector<int> par;
	vector<int> sizes;

	UnionFind(int n) {
		par.resize(n);
		sizes.resize(n);
		REP(i, n) {
			par[i] = i;
			sizes[i] = 1;
		}
	}

	int root(int a) {
		return par[a] == a ? a : par[a] = root(par[a]);
	}

	bool same(int x, int y) {
		return root(x) == root(y);
	}

	void unite(int x, int y) {
		x = root(x);
		y = root(y);
		if (x == y)return;
		if (sizes[x] < sizes[y]) swap(x, y);

		par[y] = x;
		sizes[x] += sizes[y];
	}
	int size(int x) {
		return sizes[root(x)];
	}
};

ll mypow(int n) {
	if (n == 0)return 1;
	ll a = mypow(n / 2);
	if (n & 1)return 2 * a%MOD*a%MOD;
	return a*a%MOD;
}
int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	cin >> n >> m;
	if (n <= 2||m<=1) {
		cout << 0 << endl;
		return 0;
	}
	ll x;
	cin >> x;
	Edges e(m);
	REP(i, m) {
		int u, v;
		ll w;
		cin >> u >> v >> w;
		u--; v--;
		e[i] = Edge{ u,v,w ,i };
	}
	vi used(m, 0);
	UnionFind uf(n);
	ll val = 0;
	priority_queue<Edge> q;
	REP(i, m)q.push(e[i]);
	while (!q.empty()) {
		Edge p = q.top(); q.pop();
		if (!uf.same(p.from, p.to)) {
			used[p.num] = 1;
			uf.unite(p.from, p.to);
			val += p.weight;
		}
	}
	priority_queue<Edge> minq;
	REP(i, m)if (used[i])minq.push(e[i]);
	if (val > x) {
		cout << 0 << endl;
		return 0;
	}
	else if (val < x) {
		int a = n - 1, b = 0;
		REP(i, m) {
			if (!used[i]) {
				ll tmp = e[i].weight;
				UnionFind uf(n);
				uf.unite(e[i].from, e[i].to);
				priority_queue<Edge> q = minq;
				while (!q.empty()) {
					Edge p = q.top(); q.pop();
					if (!uf.same(p.from, p.to)) {
						uf.unite(p.from, p.to);
						tmp += p.weight;
					}
				}
				if (tmp < x) {
					a++;
				}
				else if (tmp == x) {
					b++;
				}

			}
		}
		int c = m - a - b;
		cout << (mypow(c + b) - mypow(c) + MOD) % MOD * 2 % MOD << endl;
	}
	else {
		int a = n - 1;
		REP(i, m) {
			if (!used[i]) {
				ll tmp = e[i].weight;
				UnionFind uf(n);
				uf.unite(e[i].from, e[i].to);
				priority_queue<Edge> q = minq;
				while (!q.empty()) {
					Edge p = q.top(); q.pop();
					if (!uf.same(p.from, p.to)) {
						uf.unite(p.from, p.to);
						tmp += p.weight;
					}
				}

				if (tmp == x) {
					a++;
				}

			}
		}
		cout << (mypow(a) - 2)*mypow(m - a)%MOD << endl;
	}


}


Measured memory_bytes: 512