Problem:
Score : 900 points

Problem Statement

We have an undirected weighted graph with N vertices and M edges.
The i-th edge in the graph connects Vertex U_i and Vertex V_i, and has a weight of W_i.
Additionally, you are given an integer X.

Find the number of ways to paint each edge in this graph either white or black such that the following condition is met, modulo 10^9 + 7:

The graph has a spanning tree that contains both an edge painted white and an edge painted black. Furthermore, among such spanning trees, the one with the smallest weight has a weight of X.

Here, the weight of a spanning tree is the sum of the weights of the edges contained in the spanning tree.

Constraints

1 \leq N \leq 1 000

1 \leq M \leq 2 000

1 \leq U_i, V_i \leq N (1 \leq i \leq M)

1 \leq W_i \leq 10^9 (1 \leq i \leq M)

If i \neq j, then (U_i, V_i) \neq (U_j, V_j) and (U_i, V_i) \neq (V_j, U_j).

U_i \neq V_i (1 \leq i \leq M)

The given graph is connected.

1 \leq X \leq 10^{12}

All input values are integers.

Input

Input is given from Standard Input in the following format:

N M
X
U_1 V_1 W_1
U_2 V_2 W_2
:
U_M V_M W_M

Output

Print the answer.

Sample Input 1

3 3
2
1 2 1
2 3 1
3 1 1

Sample Output 1

6

Sample Input 2

3 3
3
1 2 1
2 3 1
3 1 2

Sample Output 2

2

Sample Input 3

5 4
1
1 2 3
1 3 3
2 4 6
2 5 8

Sample Output 3

0

Sample Input 4

8 10
49
4 6 10
8 4 11
5 8 9
1 8 10
3 8 128773450
7 8 10
4 2 4
3 4 1
3 1 13
5 2 2

Sample Output 4

4

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#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"));
//	if (sum == X)
//	{
//		int ans = (Pow (2, M) - 2ll * Pow (2, M - (N - 1)) % Mod + Mod) % Mod;
//		int prob = 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) ++prob;
//		}
//
//		Add (ans, 2ll * (Pow (2, M - (N - 1)) - Pow (2, M - (N - 1) - prob) + Mod) % Mod);
//		cout << ans << endl;
//	}
//	else
	{
		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 = 0;
		Add (ans, 2ll * (Pow (2, M - (N - 1) - ban) - Pow (2, M - (N - 1) - ban - prob) + Mod) % Mod);
		cout << ans << endl;

	}
}

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;
}