#include <bits/stdc++.h>

#define x first
#define y second
#define y1 Y1
#define y2 Y2
#define mp make_pair
#define pb push_back
#define DEBUG(x) cout << #x << " = " << x << endl;

using namespace std;

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

template <typename T> inline int Chkmax (T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline int Chkmin (T &a, T b) { return a > b ? a = b, 1 : 0; }
template <typename T> inline T read ()
{
	T sum = 0, fl = 1; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == '-') fl = -1;
	for (; isdigit(ch); ch = getchar()) sum = (sum << 3) + (sum << 1) + ch - '0';
	return sum * fl;
}

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

const int Maxn = 1e5 + 100;
const int Mod = 1e9 + 7;

namespace MATH
{
	inline void Add (int &a, int b) { if ((a += b) >= Mod) a -= Mod; }

	inline int Pow (int a, int b)
	{
		int ans = 1;
		for (int i = b; i; i >>= 1, a = (LL) a * a % Mod) if (i & 1) ans = (LL) ans * a % Mod;
		return ans;
	}
}

using namespace MATH;

int N, M;
LL X;
struct edge
{
	int x, y, z;
} E[Maxn];

inline int cmp (edge a, edge b) { return a.z < b.z; }

namespace DSU
{
	int fa[Maxn];

	inline void init () { for (int i = 1; i <= N; ++i) fa[i] = i; }
	inline int get_fa (int x) { return fa[x] == x ? x : fa[x] = get_fa (fa[x]); }
	inline int check (int x, int y) { return get_fa (x) == get_fa (y); }
	inline void link (int x, int y) { fa[get_fa (x)] = get_fa (y); }
}

int Vis[Maxn];

namespace TREE
{
	int Log;
	int e, Begin[Maxn], To[Maxn << 1], Next[Maxn << 1], W[Maxn << 1];
	int dep[Maxn], anc[22][Maxn], Max[22][Maxn];

	inline void add_edge (int x, int y, int z) { To[++e] = y; Next[e] = Begin[x]; Begin[x] = e; W[e] = z; }

	inline void dfs (int x, int f)
	{
		dep[x] = dep[f] + 1;
		for (int i = 1; i <= Log; ++i)
		{
			anc[i][x] = anc[i - 1][anc[i - 1][x]];
			Max[i][x] = max (Max[i - 1][x], Max[i - 1][anc[i - 1][x]]);
		}

		for (int i = Begin[x]; i; i = Next[i])
		{
			int y = To[i];
			if (y == f) continue;
			anc[0][y] = x;
			Max[0][y] = W[i];
			dfs (y, x);
		}
	}

	inline void init () { Log = log2 (N); dfs (1, 0); }

	inline int query (int x, int y)
	{
		int ans = 0;
		if (dep[x] < dep[y]) swap (x, y);
		for (int i = Log; i >= 0; --i)
			if (dep[anc[i][x]] >= dep[y])
			{
				Chkmax (ans, Max[i][x]);
				x = anc[i][x];
			}
		if (x == y) return ans;
		for (int i = Log; i >= 0; --i)
			if (anc[i][x] != anc[i][y])
			{
				Chkmax (ans, Max[i][x]), Chkmax (ans, Max[i][y]);
				x = anc[i][x], y = anc[i][y];
			}
		Chkmax (ans, max (Max[0][x], Max[0][y]));
		return ans;
	}
}

inline void Solve ()
{
	sort (E + 1, E + M + 1, cmp);

	DSU :: init ();
	LL sum = 0;
	for (int i = 1; i <= M; ++i)
	{
		int x = E[i].x, y = E[i].y, z = E[i].z;
		if (!DSU :: check (x, y))
		{
			Vis[i] = 1;
			DSU :: link (x, y);
			TREE :: add_edge (x, y, z);
			TREE :: add_edge (y, x, z);
			sum += z;
		}
	}

	TREE :: init ();
	
	if (sum > X) return void (puts("0"));

	int prob = 0, ban = 0;

	for (int i = 1; i <= M; ++i)
	{
		if (Vis[i]) continue;

		LL now = sum + E[i].z - TREE :: query (E[i].x, E[i].y);
		if (now < X) ++ban;
		if (now == X) ++prob;
	}

	int ans;
	if (sum == X) ans = (Pow (2, M) - 2ll * Pow (2, M - (N - 1) - prob) % Mod + Mod) % Mod;
	else ans = 2ll * (Pow (2, M - (N - 1) - ban) - Pow (2, M - (N - 1) - ban - prob) + Mod) % Mod;

	printf("%d\n", ans);
}

inline void Input ()
{
	N = read<int>(), M = read<int>();
	X = read<LL>();
	for (int i = 1; i <= M; ++i) E[i].x = read<int>(), E[i].y = read<int>(), E[i].z = read<int>();
}

int main()
{

#ifdef hk_cnyali
	freopen("A.in", "r", stdin);
	freopen("A.out", "w", stdout);
#endif

	Input ();
	Solve ();

	return 0;
}


Measured memory_bytes: 11260