#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <utility>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <unordered_map>
using namespace std;

#define REP(i, s) for (int i = 0; i < s; ++i)
#define ALL(v) (v.begin(), v.end())
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ EACH(it, P) { s << "<" << *it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s << endl; }

const int MAX_UF = 2100;
struct UnionFind {
	int size_uf;
	int par[MAX_UF];
	int rank[MAX_UF];
	int size_component[MAX_UF];

	UnionFind(int n = 0) { size_uf = n; for (int i = 0; i < n; ++i) par[i] = i, rank[i] = 0, size_component[i] = 1; }
	void init(int n) { size_uf = n; for (int i = 0; i < n; ++i) par[i] = i, rank[i] = 0, size_component[i] = 1; }
	int root(int x) { return par[x] == x ? x : par[x] = root(par[x]); }
	bool issame(int x, int y) { return root(x) == root(y); }
	int size(int x) { return size_component[root(x)]; }

	void connect(int x, int y) {
		x = root(x), y = root(y);
		int sx = size_component[x], sy = size_component[y];
		if (x == y) return;
		int r;
		if (rank[x] < rank[y]) par[x] = y, r = y;
		else { par[y] = x, r = x; if (rank[x] == rank[y]) ++rank[x]; }
		size_component[r] = sx + sy;
	}

	friend ostream& operator << (ostream& s, UnionFind uf) {
		map<int, vector<int> > res;
		for (int i = 0; i < uf.size_uf; ++i) {
			int r = uf.root(i);
			res[r].push_back(i);
		}
		for (map<int, vector<int> >::iterator it = res.begin(); it != res.end(); ++it) {
			s << it->second << endl;
		}
		return s;
	}
} uf;


const int MOD = 1000000007;
inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}

long long pow(long long a, long long n, long long m) {
    if (n == 0) return 1 % m;
    long long t = pow(a, n/2, m);
    t = mod(t * t, m);
    if (n & 1) t = mod(t * a, m);
    return t;
}

long long inv(long long a, long long m) {
    long long b = m, u = 1, v = 0;
    while (b) {
        long long t = a/b;
        a -= t*b; swap(a, b);
        u -= t*v; swap(u, v);
    }
    return mod(u, m);
}




const long long INF = 1LL<<60;


typedef pair<int,int> pint;
typedef pair<long long, pint> Edge;

vector<Edge> G;
int N, M;
long long X;

int main() {
  while (cin >> N >> M >> X) {
	G.clear();
	for (int i = 0; i < M; ++i) {
	  int u, v;
	  long long w;
	  cin >> u >> v >> w;
	  --u, --v;
	  G.push_back(Edge(w, pint(u, v)));
	}
	sort(G.begin(), G.end());

	long long allMin = INF;
	{
	  allMin = 0;
	  uf.init(N);
	  for (int i = 0; i < M; ++i) {
		int u = G[i].second.first;
		int v = G[i].second.second;
		long long w = G[i].first;
		if (uf.issame(u, v)) continue;
		uf.connect(u, v);
		allMin += w;
	  }
	}

	long long minNum = 0;
	long long xNum = 0;
	long long uxNum = 0;
	long long sxNum = 0;

	for (int i = 0; i < M; ++i) {
	  uf.init(N);
	  uf.connect(G[i].second.first, G[i].second.second);
	  long long tmp = G[i].first;
	  for (int j = 0; j < M; ++j) {
		if (j == i) continue;
		int u = G[j].second.first;
		int v = G[j].second.second;
		long long w = G[j].first;
		if (uf.issame(u, v)) continue;
		uf.connect(u, v);
		tmp += w;
	  }
	  if (tmp == allMin) ++minNum;
	  else if (tmp == X) ++xNum;
	  else if (tmp > X) ++uxNum;
	  else ++sxNum;
	}

	//COUT(allMin); COUT(X); COUT(minNum); COUT(xNum);
	
	if (X == allMin) {
	  long long res = pow(2LL, M, MOD);
	  long long sub = pow(2LL, M - minNum, MOD) * 2 % MOD;
	  res = mod(res - sub, MOD);
	  cout << res << endl;
	}
	else {
	  long long res1 = pow(2LL, xNum + uxNum, MOD);
	  long long res2 = pow(2LL, uxNum, MOD);
	  long long res = mod(res1 - res2, MOD) * 2;
	  res %= MOD;
	  cout << res << endl;
	}
	
  }
}
	  
	  
		  







    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    


Measured memory_bytes: 384