//#include "debug.h"
#include <assert.h>
#include <string.h>
#include <limits.h>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

template<class T>
void printa(const T *a, int n) {
	cout << '[';
	for (int i=0; i<n; i++) {
		if (i) cout << ',';
		cout << a[i];
	}
	cout << ']' << endl;
}

template<class T>
void printa_nz(const T *a, int n) {
	cout << '[';
	for (int i=0, k=0; i<n; i++) {
		if (!(a[i]==0)) {
			if (k++) cout << ',';
			cout << i << ':' << a[i];
		}
	}
	cout << ']' << endl;
}

template<class T>
void printa_i(const T *a, int n) {
	cout << '[';
	for (int i=0; i<n; i++) {
		if (i) cout << ',';
		cout << i << ':' << a[i];
	}
	cout << ']' << endl;
}

template<class T1,class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &x) {
	return os<<'('<<x.first<<','<<x.second<<')';
}

template<class T>
ostream &operator<<(ostream &os, const vector<T> &a) {
	os << '[';
	int n = a.size();
	for (int i=0; i<n; i++) {
		if (i) os << ',';
		os << a[i];
	}
	os << ']';
	return os;
}

template<class K, class T>
ostream &operator<<(ostream &os, const map<K,T> &a) {
	os << '{';
	int i = 0;
	for (auto &x: a) {
		if (i) os << ',';
		i++;
		os << x.first << ':' << x.second;
	}
	return os << '}';
}


template<class T, class C>
ostream &operator<<(ostream &os, const set<T, C> &a) {
	os << '{';
	int i = 0;
	for (auto &x: a) {
		if (i) os << ',';
		i++;
		os << x;
	}
	return os << '}';
}


template<class T>
ostream &operator<<(ostream &os, const multiset<T> &a) {
	os << '{';
	int i = 0;
	for (auto &x: a) {
		if (i) os << ',';
		i++;
		os << x;
	}
	return os << '}';
}
#include <string.h>
#include <limits.h>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

#define MOD 1000000007
//#include "math/modulo.h"
//#include "math/func.h"

template<class T>
T pow(T x, long n) {
	T y(1);
	while (n) {
		if (n%2) y = y * x;
		n /= 2;
		x = x * x;
	}
	return y;
}

template<class T>
T fac(long n) {
	T y(1);
	for (long i=2; i<n; i++)
		y = y * T(i);
	return y;
}

template<class T>
T gcd(const T &a, const T &b) {
	return a==0 ? b: gcd(b%a, b);
}

template<class T>
T gcd_ext(const T &a, const T &b, T *x, T *y) {
	if (a == 0) {
		*x = 0;
		*y = 1;
		return b;
	}
	T x1, y1;
	T g = gcd_ext(b%a, a, &x1, &y1);
	*x = y1 - (b/a) * x1;
	*y = x1;
	return g;
}


template<class T, T M>
struct modulo {
	T n;
	modulo(T n): n(n<0? n%M+M: n%M)   { }
	operator T() const                { return n;             }
	modulo operator-() const          { return modulo(-n);    }
	modulo operator+(const modulo &o) const { return modulo(n+o.n); }
	modulo operator-(const modulo &o) const { return modulo(n-o.n); }
	modulo operator*(const modulo &o) const { return modulo(n*o.n); }
	bool  operator< (const modulo &o) const { return n< o.n; }
	bool  operator<=(const modulo &o) const { return n<=o.n; }
	bool  operator> (const modulo &o) const { return n> o.n; }
	bool  operator>=(const modulo &o) const { return n>=o.n; }
	bool  operator==(const modulo &o) const { return n==o.n; }
	bool  operator!=(const modulo &o) const { return n!=o.n; }

	modulo pow(T n) const {
		return ::pow(*this, n);
	}
	modulo inv() const {
		return pow(M-2);
	}
	modulo operator/(const modulo &o) const {
		return (*this) * o.inv();
	}

	modulo div(const modulo &o) const {
		T x, y;
		T g = gcd_ext(o.n, M, &x, &y);
		if (g != 1) return 0;
		else return modulo(n * (x % M));
	}

	friend ostream &operator<<(ostream &os, const modulo &x) {
		return os << x.n;
	}
};

typedef modulo<long,MOD> I;

typedef long T;
//#include "graph/adj.h"
#include <numeric>

typedef pair<int,T> link;
const T MAXT = numeric_limits<T>::max();
typedef vector<vector<link>> graph;

//#include "graph/tree.h"


template<class graph, class link>
graph parent_to_adj(vector<link> &p) {
	int n = p.size();
	graph t(n);
	for (int i=0; i<n; i++) {
		link e = p[i];
		int j = e.first;
		if (j<0) continue;

		t[i].push_back(e);
		e.first = i;
		t[j].push_back(e);
	}
	return t;
}

template<class graph, class link>
void adj_to_parent_dfs(graph &t, vector<link> &p, int v, link f) {
	p[v] = f;
	for (auto e: t[v]) {
		int u = e.first;
		if (u==f.first) continue;
		e.first = v;
		adj_to_parent_dfs(t, p, u, e);
	}
}

template<class graph>
vector<link> adj_to_parent(graph &t, int root=0) {
	vector<link> p(t.size());
	adj_to_parent_dfs(t, p, root, link(-1,0));
	return p;
}
//#include "graph/kruskal.h"

//#include "set/union_find.h"

struct ufs {
	int n;
	vector<int> f, c;

	ufs(int n=0) {
		resize(n);
	}

	void resize(int sz) {
		n = sz;
		f.resize(n);
		c.resize(n);
		for (int i=0; i<n; i++)
			f[i] = i, c[i] = 1;
	}

	int find(int v) {
		int r, u;
		for(r=v; f[r]!=r; r=f[r]);
		for(u=v; u!=r; ) {
			int t = f[u];
			f[u] = r;
			u = t;
		}
		return r;
	}

	int merge(int a, int b) {
		a = find(a);
		b = find(b);
		if (a!=b) {
			f[a] = b;
			c[b] += c[a];
		}
		return b;
	}

	int count(int v){
		return c[find(v)];
	}
};


template<class T>
struct edge {
	int s, t;
	T w;
	bool operator<(const edge &e) const {
		return w < e.w;
	}
};

template<class E>
vector<int> kruskal(vector<E> &e, int n) {
	ufs u(n);
	vector<int> sel;
	sort(e.begin(), e.end());
	int m = e.size();
	for (int i=0; i<m; i++) {
		E &x = e[i];
		if (u.find(x.s) != u.find(x.t)) {
			u.merge(x.s, x.t);
			sel.push_back(i);
			if ((int)sel.size() == n-1) break;
		}
	}
	return sel;
}

//#include "tree/lca.h"
//#include "tree/segment.h"
//T is a group
template<class T>
class segment_tree {
public:
	int n;
	int start;
	int cap;
	vector<T> a;

	void resize(int sz) {
		n = sz;

		int len;
		for (len=1; len<=n; len*=2);
		start = len-1;
		cap = start + n;

		a.clear();
		a.resize(cap);
	}

	T sum_at(int i, int l, int r, int s, int t) {
		if (i >= cap || s>=r || t<=l) return T();
		if (s<=l && t>=r) return a[i];
		int m = (l+r)/2;
		int lc = i*2+1, rc = lc+1;
		return sum_at(lc, l, m, s, t) + sum_at(rc, m, r, s, t);
	}

	void update(int i, T x) {
		int p = start + i;
		a[p] = x;
		while (p) {
			int f = (p-1)/2;
			int lc = f*2+1, rc = lc+1;
			a[f] = rc < cap ? a[lc] + a[rc]: a[lc];
			p = f;
		}
	}

	T get(int i) {
		return a[start + i];
	}

	//sum of [s,t)
	T range_sum(int s, int t) {
		return sum_at(0, 0, start+1, s, t);
	}
};

//#include "math/group.h"
//#include "util/limit.h"

#include <limits>

template<class T>
T max_value() {
	return numeric_limits<T>::max();
}

template<class T>
T min_value() {
	return numeric_limits<T>::min();
}


/* 
//doesn't work
template<class T1, class T2>
pair<T1,T2> min_value() {
	return make_pair(min_value<T1>(), min_value<T2>());
}

template<class T1, class T2>
pair<T1,T2> max_value() {
	return make_pair(max_value<T1>(), max_value<T2>());
}
*/


template<class T>
struct minima {
	T val;
	minima(): val(max_value<T>()) {}
	minima(T val): val(val) {}
	operator T() const { return val; }
	minima operator+(const minima &o) {
		return minima(min(val, o.val));
	}
};

template<class T, class I>
struct min_info {
	T val;
	I info;
	min_info(): val(max_value<T>()) {}
	min_info(T val, I info): val(val), info(info) {}
	operator T() const { return val; }
	min_info operator+(const min_info &o) {
		if (o.val < val) return o;
		else return *this;
	}
};

template<class T>
struct maxima {
	T val;
	maxima(): val(min_value<T>()) {}
	maxima(T val): val(val) {}
	operator T() const { return val; }
	maxima operator+(const maxima &o) {
		return maxima(max(val, o.val));
	}
};

template<class T, class I>
struct max_info {
	T val;
	I info;
	max_info(): val(min_value<T>()) {}
	max_info(T val, I info): val(val), info(info) {}
	operator T() const { return val; }
	max_info operator+(const max_info &o) {
		if (val < o.val) return o;
		else return *this;
	}
};

template<class T1, class T2>
pair<T1,T2> operator+(const pair<T1,T2> &x, const pair<T1,T2> &y) {
	return pair<T1,T2>(x.first + y.first, x.second + y.second);
}


//typedef vector<vector<int,T>> tree;

template<class tree>
struct lca {
	int n;
	vector<int> first, height, euler;
	typedef min_info<int,int> node;
	segment_tree<node> segtree;

	void init(tree &t, int root=0) {
		n = t.size();
		first.resize(n);
		height.resize(n);
		euler.reserve(n*2);
		dfs(t, root, -1, 0);

		int m = euler.size();
		segtree.resize(m);
		for (int i=0; i<m; i++) {
			int v = euler[i];
			segtree.update(i, node({height[v], v}));
		}
	}

	void dfs(tree &t, int v, int f, int h) {
		height[v] = h;
		first[v] = euler.size();
		euler.push_back(v);
		for(auto e: t[v]) {
			int u = e.first;
			if (u==f) continue;
			dfs(t, u, v, h+1);
			euler.push_back(v);
		}
	}

	int query(int a, int b) {
		a = first[a], b = first[b];
		if (a>b) swap(a,b);
		node q = segtree.range_sum(a, b+1);
		return q.info;
	}
};


#define MAXN 1000
#define MAXM 2000

int n, m;
T sum;
vector<edge<T>> e;

int input() {
	if (scanf("%d %d %ld", &n, &m, &sum) < 0) return 0;
	for (int i=0; i<m; i++) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		a--, b--;
		e.push_back({a,b,c});
	}
	return 1;
}

void init() {
}

long solve() {
	vector<int> a = kruskal(e, n);

	T cost = 0;
	for (auto &i: a) cost += e[i].w;
	if (cost > sum) return 0;

	graph t(n);
	for (auto &i: a) {
		auto &x = e[i];
		t[x.s].push_back({x.t, x.w});
		t[x.t].push_back({x.s, x.w});
	}

	vector<link> p = adj_to_parent(t);

	lca<graph> l;
	l.init(t);

	set<int> sa(a.begin(), a.end());
	int equal=0, upper=0;
	T delta = sum-cost;
	for (int i=0; i<m; i++) {
		if (!sa.count(i)) {
			auto &x = e[i];
			int root = l.query(x.s, x.t);

			T maxw = LONG_MIN;
			int v[2] = {x.s, x.t};
			for (int k=0; k<2; k++) {
				for (int j=v[k]; j!=root; j=p[j].first) {
					maxw = max(maxw, p[j].second);
				}
			}
			T diff = x.w - maxw;
			//printf("%d %d->%d: %ld %ld %ld\n", x.s, x.t, root, x.w, maxw, diff);
			if (diff>delta) upper++;
			else if (diff==delta) equal++;
		}
	}
	//printf("%ld %ld eq:%d up:%d=\n", cost, sum, equal, upper);

	I r = I(2) * (I(2).pow(equal) - I(1)) * I(2).pow(upper);
	if (delta==0) {
		r = r + (I(2).pow(n-1)-I(2))*I(2).pow(m-n+1);
	}
	return (long)r;
}

void output(long ans) {
	printf("%ld\n", ans);
}

void cleanup() {
	e.clear();
}

int main() {
	//int ca; scanf("%d", &ca);
	while (input()) {
		init();
		output(solve());
		cleanup();
		//break;
	}
}





Measured memory_bytes: 512