/* Generated by powerful Codeforces Tool
 * You can download the binary file in here https://github.com/xalanq/cf-tool (Windows, macOS, Linux)
 * Author: alireza_kaviani
 * Time: 2020-07-24 11:13:29
**/
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

#define all(x)                      (x).begin(),(x).end()
#define Sort(x)                     sort(all((x)))
#define X                           first
#define Y                           second
#define sep                         ' '
#define endl                        '\n'
#define SZ(x)                       ll(x.size())

ll poww(ll a, ll b, ll md) {
    return (!b ? 1 : (b & 1 ? a * poww(a * a % md, b / 2, md) % md : poww(a * a % md, b / 2, md) % md));
}

const ll MAXN = 1e5 + 10;
const ll LOG = 22;
const ll INF = 8e18;
const ll MOD = 1e9 + 7; // 998244353; // 1e9 + 9;

ll n , m , x , mstCost , par[LOG][MAXN] , mx[LOG][MAXN] , H[MAXN] , P[MAXN] , sz[MAXN];
vector<pll> adj[MAXN];
vector<pair<ll , pll>> E;

int Find(int v){
    return (P[v] == -1 ? v : P[v] = Find(P[v]));
}

int Union(int v , int u){
    v = Find(v) , u = Find(u);
    if(v == u)  return 0;
    if(sz[v] < sz[u])   swap(v , u);
    P[u] = v;
    sz[v] += sz[u];
    return 1;
}

void DFS(int v , int p = 0 , int w = 0){
    mx[0][v] = w;
    par[0][v] = p;
    H[v] = H[p] + 1;
    for(pll i : adj[v]){
        int u = i.X , W = i.Y;
        if(u != p)  DFS(u , v , W);
    }
}

int getPar(int v , int h){
    for(int i = 0 ; i < LOG ; i++)  if(h & (1 << i))    v = par[i][v];
    return v;
}

int getMax(int v , int h){
    ll ans = 0;
    for(int i = 0 ; i < LOG ; i++)  if(h & (1 << i))    ans = max(ans , mx[i][v]) , v = par[i][v];
    return ans;
}

int getLCA(int v , int u){
    if(H[u] < H[v]) swap(u , v);
    u = getPar(u , H[u] - H[v]);
    if(v == u)  return v;
    for(int i = LOG - 1 ; i >= 0 ; i--) if(par[i][v] != par[i][u])  v = par[i][v] , u = par[i][u];
    return par[0][v];
}

ll getMaxPath(int v , int u){
    int lca = getLCA(v , u);
    return max(getMax(v , H[v] - H[lca]) , getMax(u , H[u] - H[lca]));
}

int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    fill(P , P + MAXN , -1);
    fill(sz , sz + MAXN , 1);

    cin >> n >> m >> x;
    for(int i = 0 ; i < m ; i++){
        int v , u , w;
        cin >> v >> u >> w;
        E.push_back({w , {v , u}});
    }
    sort(all(E));
    for(pair<ll , pll> i : E){
        ll w = i.X , v = i.Y.X , u = i.Y.Y;
        if(Union(v , u)){
            adj[v].push_back({u , w});
            adj[u].push_back({v , w});
            mstCost += w;
        }
    }
    //cout << mstCost << endl;
    DFS(1);
    for(int i = 1 ; i < LOG ; i++)  for(int j = 0 ; j <= n ; j++)   par[i][j] = par[i - 1][par[i - 1][j]] , mx[i][j] = max(mx[i - 1][j] , mx[i - 1][par[i - 1][j]]);
    int les = 0 , eq = 0 , gr = 0;
    for(pair<ll , pll> i : E){
        ll w = i.X , v = i.Y.X , u = i.Y.Y;
        ll cost = mstCost - getMaxPath(v , u) + w;
        //cout << v << sep << u << sep << w << sep << cost << sep << getMaxPath(v , u) << endl;
        if(cost < x)    les++;
        if(cost == x)   eq++;
        if(cost > x)    gr++;
    }
    //cout << les << sep << eq << sep << gr << endl;
    if(n <= 2)  return cout << 0 << endl , 0;
    if(x == mstCost)    return cout << (poww(2 , eq , MOD) + MOD - 2) * poww(2 , gr , MOD) % MOD << endl , 0;
    cout << 2 * (poww(2 , eq , MOD) - 1) * poww(2 , gr , MOD) % MOD << endl;

    return 0;
}
/*

*/


Measured memory_bytes: 8208